android – 如果应用程序处于非活动状态,CursorLoader如何自动更新视图?

我一直在做一个小的待办事项列表应用程序。我使用CursorLoader从内容提供商更新ToDolistview。我有一个函数onNewItemAdded(),当用户在文本视图中输入一个新项目并点击进入时调用该函数。请参考:

public void onNewItemAdded(String newItem) {
    ContentResolver cr = getContentResolver();

    ContentValues values = new ContentValues();
    values.put(ToDoContentProvider.KEY_TASK, newItem);

    cr.insert(ToDoContentProvider.CONTENT_URI, values);
    // getLoaderManager().restartLoader(0, null, this); // commented for the sake of testing
}

@Override
protected void onResume() {
    super.onResume();
    //getLoaderManager().restartLoader(0, null, this); // commented for the sake of testing
}

public Loader<Cursor> onCreateLoader(int id, Bundle args) {

    CursorLoader loader = new CursorLoader(this,
            ToDoContentProvider.CONTENT_URI, null, null, null, null);
    Log.e("GOPAL", "In the onCreateLoader");
    return loader;
}

public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {

    int keyTaskIndex = cursor.getColumnIndexOrThrow(ToDoContentProvider.KEY_TASK);
    Log.e("GOPAL", "In the onLoadFinished");
    todoItems.clear();
    if (cursor.moveToNext() == false) Log.e("GOPAL", "Empty Cursor");
    else {
        while (cursor.moveToNext()) {
            ToDoItem newItem = new ToDoItem(cursor.getString(keyTaskIndex));
            todoItems.add(newItem);
        }
        aa.notifyDataSetChanged(); // aa is arrayadapter used for the listview
    }
}

我已经阅读,每当内容提供商数据库中有数据更改时,CursorLoader会自动更新视图。这意味着我想,getLoaderManager()。restartLoader(0,null,this)必须被隐式调用,只要数据有变化,对吧?
          但是没有发生。每当我添加一个新项目(该项目从onNewItemAdded添加到db,但是restartLoader未被显式调用)时,暂停此活动并将其恢复。我没有看到重新启动引导器的任何隐式调用(即使数据库已更改),并且列表视图也不会被添加的新项目更新。这是为什么? CursorLoader如何自动更新视图,即使应用程序不活动?
谢谢 :)

编辑:我的内容提供者插入中也使用了getContext()。getContentResolver()。notifyChange(insertedId,null))。

最佳答案
我找到了我的问题的答案。一般来说,CursorLoader不会自动检测数据变化并加载它们进行查看。我们需要跟踪URI进行更改。这可以通过以下步骤完成:

>通过游标在内容解析器中注册观察者:(在ContentProvider的查询方法中完成)
cursor.setNotificationUri(getContext()。getContentResolver(),uri);
>现在,当使用insert()/ delete()/ update()的URI基础数据有任何变化时,我们使用以下方式通知内容转换器有关更改:

getContext()。getContentResolver()。notifyChange(insertedId,null);
观察者收到,我们在第一步注册,并调用ContentResolver.query(),它调用Contentent providers query()方法返回一个新的游标到loaderManager。 LoaderManager调用onLoadFinished传递此游标,以及Cursorloader,我们用新数据更新View(使用adapter.swapcursor())。

对于自定义AsyncTaskLoaders:

有时我们需要我们的自定义加载器而不是CursorLoader。这里我们可以使用除光标之外的其他对象指向加载的数据(如列表等)。在这里,我们不会有通过游标通知ContentResolver的先例。应用程序也可能没有内容提供程序来跟踪URI更改。在这种情况下,我们使用BroadcastReceiver或显式的ContentObserver实现自动视图更新。如下:

>我们需要定义我们的自定义加载器,它扩展AsyncTaskLoader并实现其所有的抽象方法。与CursorLoader不同,我们的自定义加载程序可能使用内容提供程序也可能不使用内容提供程序,并且构造函数可能不会调用ContentResolver.query(),当此加载程序被设置时。所以我们使用广播接收器来达到这个目的。
>我们需要在抽象AsyncTaskLoader类的OnStartLoading()方法中实例化一个BroadCastReceiver或ContentObserver。
> BroadCast接收器应该被定义为从内容提供商或任何系统事件(如新的应用程序安装)接收数据变化广播,并且必须调用加载程序的onContentChanged()方法来通知加载器数据更改。加载程序自动执行其他操作以加载更新的数据,并调用onLoadFinished()来更新视图。

详情请参考:http://developer.android.com/reference/android/content/AsyncTaskLoader.html

我发现这非常有用的清楚的解释:http://www.androiddesignpatterns.com/2012/08/implementing-loaders.html

转载注明原文:android – 如果应用程序处于非活动状态,CursorLoader如何自动更新视图? - 代码日志