2014-10-01 51 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