如果在CursorLoader注册ContentObserver之前调用notifyChange(),则CursorLoader不会刷新

时间:2013-07-28 18:38:10

标签: android android-contentprovider android-loadermanager android-cursorloader

我有CursorLoader从本地SQLite数据库加载数据。

SQLite中的数据实际上是远程API响应的缓存副本,因此每当SQLite查询时,我都会开始异步刷新CursorLoader数据

以下是我在ContentProvider中回复数据查询时所遵循的一系列步骤:

  1. 在返回的游标上调用SQLite cached data. cursor.setNotificationUri(getContext().getContentResolver(), uri)

  2. 启动对远程API的异步调用。收到回复后,系统会调用getContext().getContentResolver().notifyChange(uri, null)

  3. 睡眠5秒会导致CursorLoader收到光标延迟。 (这样做很容易重现我的问题)。

  4. Step 1中获得的光标返回CursorLoader

  5. 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代码中出现大量膨胀。

2 个答案:

答案 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方法,您可以要求加载器再次加载数据