4

我正在尝试使用使用 Commonsware 的 Loader 的适配器来实现 DataListFragment。此 Loader 直接使用 SQLiteDatabase,不需要使用 ContentProvider。

关于 Loaders 的 android 参考声明:“当 Loaders 处于活动状态时,它们应该监视其数据源并在内容更改时提供新结果。”

在我的 SQLiteCursor 实现下(如下),这不会发生。OnLoadFinished()被调用一次,就是这样。据推测,可以Loader.onContentChanged()在底层数据库发生更改的地方插入调用,但通常数据库代码类不知道加载器,所以我不确定实现这一点的最佳方法。

是否有人对使加载程序“数据感知”有任何建议,或者我应该将数据库内容包装为 ContentProvider 并改用 CursorLoader?

import com.commonsware.cwac.loaderex.SQLiteCursorLoader;

public class DataListFragment extends ListFragment implements    LoaderManager.LoaderCallbacks<Cursor>{

protected DataListAdapter  mAdapter;     // This is the Adapter being used to display the list's data.
public SQLiteDatabase      mSqlDb;
private static final int   LOADER_ID = 1;

@Override 
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    int rowlayoutID = getArguments().getInt("rowLayoutID");
    // Create an empty adapter we will use to display the loaded data.
    // We pass 0 to flags, since the Loader will watch for data changes
    mAdapter = new DataListAdapter(getActivity(),rowlayoutID, null , 0);
    setListAdapter(mAdapter);
    // Prepare the loader.  Either re-connect with an existing one,
    // or start a new one.
    LoaderManager lm = getLoaderManager();
    // OnLoadFinished gets called after this, but never again.
    lm.initLoader(LOADER_ID, null, this);
}
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    String sql="SELECT * FROM "+TABLE_NAME+";";
    String[] params = null;
    SQLiteCursorLoader CursorLoader = new SQLiteCursorLoader(getActivity(), mSqlDb, sql, params);
    return CursorLoader;
}
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    // Swap the new cursor in.  (The framework will take care of closing the old cursor once we return.)
    mAdapter.swapCursor(data);
    // The list should now be shown.
    if (isResumed()) { setListShown(true);} 
    else { setListShownNoAnimation(true); }
}
public void onLoaderReset(Loader<Cursor> loader) {
    // This is called when the last Cursor provided to onLoadFinished()
    // above is about to be closed.  We need to make sure we are no
    // longer using it.
    mAdapter.swapCursor(null);
}
4

1 回答 1

20

文档有Loader缺陷。

100%Loader内置于 Android 本身的实现“监控其数据源并在内容发生变化时提供新结果”。由于到目前为止LoaderAndroid 本身只内置了一个实现,因此他们的文档是准确的。

但是,引用我的一本书更新,应该在一两个小时内发布:

框架中没有任何东西需要这种行为。此外,在某些情况下这样做显然是个坏主意——想象一下加载器从 Internet 加载数据,需要不断地轮询某些服务器以查找更改。

如果您通过它路由所有数据库修改,我确实计划增加SQLiteCursorLoader至少一点对数据库更改的了解。这也会有限制,因为您不会Loader在活动之间共享对象(更不用说从服务访问它们了)。

这样做的唯一原因CursorLoader是因为它使用了ContentProvider一个单例,因此可以了解所有操作。

目前,您的代码中负责插入、更新和删除的任何部分都需要点击SQLiteCursorLoader肩膀并让它更新,或者通知活动更改(例如,从 a 广播Service)以便活动可以轻拍SQLiteCursorLoader肩膀。

于 2012-01-30T12:22:53.437 回答