我一直在一个小的待办事项清单应用程序。 我用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)
在我的内容提供商的插入。
我发现我的问题的答案。 一般而言,CursorLoader不会自动检测数据的变化,并加载他们查看。 我们需要跟踪URI更改。 这可以通过以下步骤来完成:
使用通过光标登记在内容解析器观察员:(在的ContentProvider的查询方法完成)
cursor.setNotificationUri(getContext().getContentResolver(), uri);
现在,当有使用URI基础数据的任何改变insert()
/ delete()
/ update(),
我们会通知ContentResolver
有关使用变化:
getContext().getContentResolver().notifyChange(insertedId, null);
这是由观察者接收到,我们登记在步骤-1和这个调用ContentResolver.query()
其依次调用ContentProvider
的query()
方法返回一个新鲜光标LoaderManager
。 LoaderManager
调用onLoadFinished()
通过这个指针,与沿CursorLoader
我们更新视图(使用Adapter.swapCursor()
与新鲜的数据。
对于自定义AsyncTaskLoaders:
有时,我们需要我们自定义的加载,而不是CursorLoader。 在这里,我们可以用比其他光标对象一些其它指向加载的数据(如列表等)。 在此,我们不会有previlige通过光标通知ContentResolver的。 该应用程序也可能没有一个内容提供商,以跟踪URI的变化。 在这种情况下,我们用广播接收器或明确ContentObserver实现自动视图更新用。 这是如下:
- 我们需要定义延伸我们的定制加载
AsyncTaskLoader
并实现其所有的抽象方法。 不像CursorLoader
,我们的自定义引导可能会或可能不会使用内容提供商,它的构造函数不能调用ContentResolver.query()
当该装载机instatiated。 所以,我们用广播接收器为服务宗旨。 - 我们需要实例化一个
BroadCastReceiver
或ContentObserver
在OnStartLoading()
抽象的方法AsyncTaskLoader
类。 - 该广播接收器应该被定义为接收从内容提供商或任何系统事件(例如安装新的应用程序)的数据更改广播,它必须调用装载机
onContentChanged()
方法,通知有关数据变化装载机。 装载机自动完成余下加载更新的数据,并调用onLoadFinished()
来更新视图。
欲了解更多详情,请参阅本: http://developer.android.com/reference/android/content/AsyncTaskLoader.html
我发现这非常有用的明确的解释: http://www.androiddesignpatterns.com/2012/08/implementing-loaders.html
好吧,我想你可以重新启动某些事件装载机。 例如,在我的情况我有待办事项的活动。 在点击“添加”选项,它会启动它有观点养活新TODO新的活动。
我使用下面的父活动的onActivityResult代码()
getLoaderManager().restartLoader(0, null, this);
这对我来说可以。 请分享,如果有任何更好的方法。
得到您的装载机的参考,同时初始化如下
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?