我们正试图连接我们的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#查询被调用。如果我尝试在当前线程上进行api调用,我会得到一个networkonmainthreadexception。
我试图通知光标数据已经改变,但也没有成功。
getContext().getContentResolver().notifyChange(Uri.parse("content://com.foo.test"), null);
...
cursor.setNotificationUri(getContext().getContentResolver(), Uri.parse("content://com.foo.test"));
无论如何我可以强制O.S在一个单独的线程上调用内容提供者,或者至少通知搜索光标有新的内容吗?
谢谢
答案 0 :(得分:6)
其中一个解决方案是设置内容提供商流程
android:process:":androidtv"
并在进行网络呼叫之前将ThreadPolicy设置为LAX
ThreadPolicy tp = ThreadPolicy.LAX;
StrictMode.setThreadPolicy(tp);
通过在不同的进程中运行contentprovider,即使查询在主线程上运行,也不会影响您的UI操作
答案 1 :(得分:1)
我也一直在努力解决这个问题,因为我没有找到阻止用户界面接受的当前接受的答案。
然而,谷歌电视团队的MarcBächinger表示,这只是模拟器的一个问题。在更新的版本(例如当前可用硬件中的版本)中,搜索提供程序在后台线程中调用,这完全避免了这个问题。
我已经能够在Nexus播放器上测试它,并确认它能正常工作。
答案 2 :(得分:0)
编辑回答
我自己也经历过这个问题,我不得不依赖于已接受答案的解决方案。但是,我注意到在“全局搜索”中键入明显滞后。框。这种滞后是:
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));
}
答案 3 :(得分: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;
}
我们将继续寻找是否可以在没有延迟的情况下重新挂钩。