【问题标题】:Getting SQLiteCursorLoader to observe data changes让 SQLiteCursorLoader 观察数据变化
【发布时间】:2012-02-22 01:32:20
【问题描述】:

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

关于 Loaders 的 android 参考声明: “当加载器处于活动状态时,它们应该监控数据的来源,并在内容发生变化时提供新的结果。”

在我的 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);
}

【问题讨论】:

    标签: android android-cursorloader commonsware-cwac


    【解决方案1】:

    Loader 文档存在缺陷。

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

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

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

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

    CursorLoader 能够正常工作的唯一原因是它使用了ContentProvider——因此可以感知所有操作的单例。

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

    【讨论】:

    • 我整天都在浏览 Loader 源代码,并开始怀疑。谢谢。
    • 对我来说一个可行的解决方法(我正在使用内容提供商)是使用:getLoaderManager().restartLoader(0, null, this);
    • @zx81 如果您使用的是 ContentProvider,那么我认为您不需要这样做,相反,您应该通知加载程序在您的 URI 逻辑中发生了更改...否?
    • @AutoM8R:SQLiteCursorLoader 专门用于没有 ContentProvider 的情况。
    • @CommonsWare 我现在在我的项目中使用它,喜欢它!我是直接回复zx81的cmets。 :)
    猜你喜欢
    • 2019-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多