内容提供商瓦特/光标 - 就会被杀死(如何通知客户端)(Content Provider w/ Cu

2019-09-28 20:52发布

我有在APK内容提供商正在提供基于REST的搜索结果为多个客户端应用程序。

基本上,客户端请求经由内容解析器光标,然后触发一个意图的服务请求来触发搜索..

在提供者,光标返回到表,并且每个意图服务请求填充相应的表,并触发NotifyDataSetChanged。

作品真的很好..我遇到的唯一问题是,如果供应商被杀害由于某种原因光标上的客户端APK不会改变(做pkill的-9 com.myprovider.name测试),但应用程序不通知该供应商走了,就需要重新连接到数据库..所以它会继续火过服务的意图,光标永远不会被更新的b / C它不再依赖于底层数据库..

我通过我们的代码去试试,看看我们捕捉一些例外,也许隐藏了潜在的问题,但我没有看到它..

我试着明确地做一个cursor.close()在敲定/ onLowMemory /关机()的供应商..没有出现被触发。

我注意到,这发生在logcat的

09-10 13:58:03.015: I/ActivityThread(4268): Removing dead content provider: com.myprovider.name (called from the calling app)

任何方式来获得调用应用程序这个通知?

Answer 1:

因此,一些研究之后,我有一个可行的解决方案,但会如果任何人有任何其他建议,他们将不胜感激。

由于这样的事实,我们使用的是ContentProvider的得到一个光标,然后就通过IntentService更新后端数据。 我们抓住光标当我们的用户在他们的搜索的第一个字符,如果光标数= 0,那么我们将展示一个空列表的消息,否则我们显示该光标的项目列表..

**注:有些光标处理可能需要进行调整了一下,我没有看到任何崩溃瓦特/有光标撕开我们的适配器,成为空,但您的里程可能会有所不同。(这是关于如何使用contentProviderClient())

**注意:每文档,你必须释放contentProviderClient()时不再使用。

由于内容提供商应该返回一个类型,我们可以做以下..

所以我们定义一个成员变量

private ContentProviderClient contentProviderClient = null;

然后,当我们的用户改变了我们最终调用搜索字符串

public void setFilter( String searchFilter ) {
   searchedString = !TextUtils.isEmpty(filter) ? filter : "";

   boolean reload = false;               // Reloads content provider

   // contentProvider is null on first connection, assumed to be up on 
   // subsequent connections as we only close the cursor and 
   // contentProviderClient when we exit

   if (contentProviderClient != null) {
      try {
      // getType will throw an exception if the instance of the 
      // contentProvider went away (killed by user/memory collection etc)

         contentProviderClient.getType(searchFactoryUri);
      } catch (RemoteException e) {
         if( searchAdapter != null ) {
            Cursor cursor = searchAdapter.getCursor();
            cursor = null; 
            reload = true;
            contentProviderClient.release();
         }
      }
   }

   // This is for first search initialization or reloading cursor 
   // if the content provider went away for some unknown reason.

   if( this.searchAdapter == null || reload ){
      Cursor cursor = getActivity().getContentResolver().query(
            MY_URI,
            null,
            null,
            null,
            null);

   contentProviderClient = getActivity()
             .getContentResolver()
             .acquireContentProviderClient(MY_URI);

   cursor.setNotificationUri(getActivity.getContentResolver(), MY_URI);

   // DO what ever you need to after getting cursor, a cursor loader
   // would be a better implementation here, but simplifying it as 
   // I don't want to over-complicate the example.

   myList.setAdapter(searchAdapter);

   }
   getActivity().startService(MyUtil.getSearchIntent( MY_URI, searchedString );
}

@Override
public void onDestroy() {
   super.onDestroy();
   // Cleanup adapter, cursor, provider client
   if (searchAdapter != null) {
      searchAdapter.changeCursor(null); // Closes existing cursor 
   }
   if (contentProviderClient != null) {
     contentProviderClient.release();  // Release client
   }
}


文章来源: Content Provider w/ Cursor - Gets Killed (how to notify client)