我有CursorLoader
从本地SQLite
数据库加载数据。
SQLite
中的数据实际上是远程API
响应的缓存副本,因此每当SQLite
查询时,我都会开始异步刷新CursorLoader
数据
以下是我在ContentProvider
中回复数据查询时所遵循的一系列步骤:
在返回的游标上调用SQLite
cached data. cursor.setNotificationUri(getContext().getContentResolver(), uri)
。
启动对远程API
的异步调用。收到回复后,系统会调用getContext().getContentResolver().notifyChange(uri, null)
。
睡眠5
秒会导致CursorLoader
收到光标延迟。 (这样做很容易重现我的问题)。
将Step 1
中获得的光标返回CursorLoader
。
在API
可以在获取的游标上注册notifyChange()
之前,异步远程CursorLoader
调用完成(以及ContentObserver
被调用)的可能性较小但可能的情况通过致电registerContentObserver(cursor, mObserver)
[请http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.1_r1/android/content/CursorLoader.java#CursorLoader.loadInBackground%28%29],CursorLoader
错过了数据更改通知,因此Activity
未看到更新的数据。
我可以通过编写LoaderCallBacks
来解决这个问题,使数据加载两次 - 首先只加载缓存数据,然后发出refresh
请求。这样CursorLoader
就可以在ContentObserver
来电开始之前注册refresh
。
然而,理想情况下,这应由CursorLoader
本身处理,因为CursorLoader
通告光标的自动更新。在每个Activity
中执行此操作会导致Activity
代码中出现大量膨胀。
答案 0 :(得分:1)
我的方法是在开始加载光标之前注册观察者。您需要注册Uri而不是光标。
getActivity().getContentResolver().registerContentObserver(
your_Uri, true,
new YourObserver(mHandler));
getLoaderManager().initLoader(0, null, this);
答案 1 :(得分:0)
在初始化时获取对加载程序的引用,如下所示
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方法,您可以要求加载器再次加载数据