如何CursorLoader自动更新,即使应用程序处于非活动状态的看法?(How do Cursor

2019-07-22 02:00发布

我一直在一个小的待办事项清单应用程序。 我用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)具有被称为隐含每当有数据的变化,对不对? 但是,情况并非如此。 每当我添加一个新的项目(该项目被添加到从DB onNewItemAdded ,但restartLoader不显式调用),暂停此活动,并恢复回来。 我看不到restartLoader(即使数据库被改变)的任何隐式调用和列表视图也不会更新与新产品加入。 这是为什么? 如何做一个CursorLoader自动更新,即使应用程序是不活跃的视图??? 谢谢 :)

编辑:我也用getContext().getContentResolver().notifyChange(insertedId, null)在我的内容提供商的插入。

Answer 1:

我发现我的问题的答案。 一般而言,CursorLoader不会自动检测数据的变化,并加载他们查看。 我们需要跟踪URI更改。 这可以通过以下步骤来完成:

  1. 使用通过光标登记在内容解析器观察员:(在的ContentProvider的查询方法完成)
    cursor.setNotificationUri(getContext().getContentResolver(), uri);

  2. 现在,当有使用URI基础数据的任何改变insert() / delete() / update(),我们会通知ContentResolver有关使用变化:

    getContext().getContentResolver().notifyChange(insertedId, null);

  3. 这是由观察者接收到,我们登记在步骤-1和这个调用ContentResolver.query()其依次调用ContentProviderquery()方法返回一个新鲜光标LoaderManagerLoaderManager调用onLoadFinished()通过这个指针,与沿CursorLoader我们更新视图(使用Adapter.swapCursor()与新鲜的数据。

对于自定义AsyncTaskLoaders:

有时,我们需要我们自定义的加载,而不是CursorLoader。 在这里,我们可以用比其他光标对象一些其它指向加载的数据(如列表等)。 在此,我们不会有previlige通过光标通知ContentResolver的。 该应用程序也可能没有一个内容提供商,以跟踪URI的变化。 在这种情况下,我们用广播接收器或明确ContentObserver实现自动视图更新用。 这是如下:

  1. 我们需要定义延伸我们的定制加载AsyncTaskLoader并实现其所有的抽象方法。 不像CursorLoader ,我们的自定义引导可能会或可能不会使用内容提供商,它的构造函数不能调用ContentResolver.query()当该装载机instatiated。 所以,我们用广播接收器为服务宗旨。
  2. 我们需要实例化一个BroadCastReceiverContentObserverOnStartLoading()抽象的方法AsyncTaskLoader类。
  3. 该广播接收器应该被定义为接收从内容提供商或任何系统事件(例如安装新的应用程序)的数据更改广播,它必须调用装载机onContentChanged()方法,通知有关数据变化装载机。 装载机自动完成余下加载更新的数据,并调用onLoadFinished()来更新视图。

欲了解更多详情,请参阅本: http://developer.android.com/reference/android/content/AsyncTaskLoader.html

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



Answer 2:

好吧,我想你可以重新启动某些事件装载机。 例如,在我的情况我有待办事项的活动。 在点击“添加”选项,它会启动它有观点养活新TODO新的活动。

我使用下面的父活动的onActivityResult代码()

getLoaderManager().restartLoader(0, null, this);

这对我来说可以。 请分享,如果有任何更好的方法。



Answer 3:

得到您的装载机的参考,同时初始化如下

 Loader dayWeatherLoader = getLoaderManager().initLoader(LOADER_DAY_WEATHER, null, this);

然后创建扩展ContentObserver一类如下

 class DataObserver extends ContentObserver {

    public DataObserver(Handler handler) {
        super(handler);
    }

    @Override
    public void onChange(boolean selfChange, Uri uri) {
        dayWeatherLoader.forceLoad();
    }
}

然后生命周期的onResume方法内部寄存器内容观察者如下

@Override
public void onResume() {
    super.onResume();
    getContext().getContentResolver().registerContentObserver(CONTENTPROVIDERURI,true,new DayWeatherDataObserver(new Handler()));
}

每当有内容提供者的基础数据发生变化,contentobserver的的onChange方法将被调用,您可以问装载机再次加载数据



文章来源: How do CursorLoader automatically updates the view even if the app is inactive?