7

我们正在尝试连接我们的 AndroidTV 应用程序以将结果附加到全局搜索中。我遇到了一个问题,因为系统在主线程上调用我的内容提供程序,所以我无法进行 api 调用来获取结果。

@Override
public Cursor query(Uri uri, String[] projection, String search, String[] selectionArgs, String searchOrder) {

    ... Logic here that calls the API using RxJava / Retrofit

    return cursor;
}


<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="@string/foo"
android:searchSettingsDescription="@string/foo_results"
android:includeInGlobalSearch="true"
android:searchSuggestAuthority="com.foo.search.provider"
android:searchSuggestIntentAction="android.intent.action.VIEW" />

<provider
   android:authorities="com.foo.search.provider"
   android:name=".search.GlobalSearchProvider"
   android:exported="true"/>

当我进行全局搜索时,我可以看到 ContentProvider#query 被调用。如果我尝试在当前线程上进行 api 调用,我会得到 networkonmainthreadexception。

我试图通知游标数据已更改但也没有成功。

getContext().getContentResolver().notifyChange(Uri.parse("content://com.foo.test"), null);
...
cursor.setNotificationUri(getContext().getContentResolver(), Uri.parse("content://com.foo.test"));

无论如何我可以强制操作系统在单独的线程上调用内容提供程序,或者至少通知搜索光标有新内容?

谢谢你

4

4 回答 4

6

一种解决方案可以是设置内容提供者进程

android:process:":androidtv"

并在进行网络调用之前将 ThreadPolicy 设置为 LAX

ThreadPolicy tp = ThreadPolicy.LAX;
StrictMode.setThreadPolicy(tp);

通过在不同的进程中运行 contentprovider,即使查询运行在主线程上,也不会影响您的 UI 操作

于 2014-10-01T03:52:15.383 回答
1

我也为此苦苦挣扎,因为我没有找到当前接受的阻止 UI 的答案。

但是,根据 Google TV 团队的 Marc Bächinger 的说法,这只是模拟器的问题。在最近的构建中(例如当前可用硬件中的那些),搜索提供程序在后台线程中调用,这完全避免了这个问题。

我已经能够在 Nexus Player 上对其进行测试,并且可以确认它可以正常工作。

来源: https: //plus.google.com/+DanielCachapa/posts/dbNMoyoRGEi

于 2015-04-23T07:03:22.417 回答
0

编辑的答案

我自己也遇到过这个问题,我不得不依赖接受的答案提出的解决方案。但是,我注意到在“全局搜索”框中输入时有明显的滞后。这个滞后是:

  1. 由应用程序引起,因为它的删除使滞后消失
  2. 很可能是由于查询应用程序的同步等待 - 因为我们的应用程序执行两个网络请求,该query()方法需要时间才能完成,导致这种滞后

我发现:androidtv不需要单独的进程 ( )。通过设置ThreadPolicy.LAX配置,网络请求仍然会执行而不抛出NetworkOnMainThreadException.

我仍然不明白为什么会有滞后。


原始答案

我不相信公认的答案,虽然它确实有效,但它是正确的方法。

query()调用该方法后,您应该生成一个新的线程/任务/作业来执行网络调用(因此,避免使用NetworkOnMainThreadException),一旦适配器获得所需的数据,它将更新适配器。

有不同的方法可以做到这一点。您可以使用回调或事件总线(例如 Otto)。这是我调用来更新适配器的方法:

public void updateSearchResult(ArrayList<Data> result) {
    mListRowAdapter.clear();
    mListRowAdapter.addAll(0, result);
    HeaderItem header = new HeaderItem(0, "Search results", null);
    mRowsAdapter.add(new ListRow(header, mListRowAdapter));
}
于 2014-10-04T07:46:05.480 回答
0

为了解决在查询方法中使用 API 在全局搜索中显示结果的问题,我基本上所做的是在获取 api 结果和查询 db 以返回游标的结果之间引入延迟。

您可以通过

private Cursor getSuggestions(final String query) {
    Cursor cursor;
    cursor = getCursor(query);
    if (cursor==null || cursor.getCount() == 0) {
    //apiCall
      try {
        Thread.sleep(X millis);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      cursor = getCursor(query);
    }
    return cursor;
  }

将继续寻找,我们是否可以在不使用延迟的情况下重新连接某种钩子。

于 2018-10-17T06:28:23.120 回答