2014-10-01 52 views
6

我们试图连接我们的AndroidTV应用程序以将结果附加到全局搜索中。我遇到了一个问题,我无法通过api调用来获取结果,因为系统在主线程上调用了我的内容提供者。在全球搜索的内容提供商处调用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#查询被调用。如果我尝试在当前线程上执行api调用,则会收到networkonmainthreadexception。

我试图通过游标提示数据已经改变但没有成功。

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

反正我有可以强制O.S呼吁在一个单独的线程的内容提供商,或者至少通知光标有新的内容搜索?

谢谢

回答

6

其中一种解决方案可以设置内容提供商过程

android:process:":androidtv" 

,并设置ThreadPolicy到LAX只是让网络通话

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

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

+0

请问您可以看看下面的答案吗? – Sebastiano 2014-10-14 08:12:27

+0

@dextor我想你可以尝试改变你的searchableinfo出现在SearchManager.getSearchablesInGlobalSearch()列表中的顺序。我认为你可以通过更改可搜索活动的名称来完成此操作。所以你的应用程序搜索将由搜索应用程序最后完成,但我不确定它是否会工作。进一步说,创建一个独立进程的目的是让查询不会在主线程上运行,如果您只设置了策略宽松,查询仍然会在主线程中运行,并且UI操作可能会延迟,或者您可能会收到ANR – nandeesh 2014-10-14 10:00:00

+0

我的搜索结果已经显示为最后结果,所以这是不行的。我知道,在单独的流程上运行“解决”了这个问题,但是我注意到,由此产生的延迟高于在同一流程上运行。我无法弄清楚为什么。 – Sebastiano 2014-10-14 10:08:19

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)); 
} 
+0

我无法启动一个单独的线程,因为我无法通知AndroidTV框架光标中的数据已更新。 – Darussian 2014-10-04 15:14:26

+0

为什么不呢? (也许我错过了一些东西) – Sebastiano 2014-10-04 18:14:27

+0

我并不控制框架的功能,他们也没有添加任何逻辑让我反馈给它。 – Darussian 2014-10-05 14:21:45

0

我也挣扎着这个,因为我没有找到阻塞UI可以接受目前公认的答案。

但是,根据Google TV团队的MarcBächinger的说法,这只是模拟器的一个问题。在更新的版本中(例如当前可用硬件中的版本),搜索提供程序将在后台线程中调用,从而完全避免该问题。

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

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