Android 基础数据更改时未刷新游标加载程序

Android 基础数据更改时未刷新游标加载程序,android,android-cursorloader,Android,Android Cursorloader,我有一个内容提供者、一个内容解析器和一个游标加载器。加载程序用于间接填充listview(即不是一个简单的游标适配器,而是一个数组适配器,因为我需要使用游标的结果来收集其他数据) 当我更改基础数据时,listview不会重新填充,因为不会调用onLoadFinished(Loader,Cursor)回调 正如我在写这篇文章时所建议的,在这个问题上有很多问题。 如 所有的问题都指出了两件事: 在contentproviderquery()方法中,您需要告诉光标关于通知的信息 c.setNot

我有一个内容提供者、一个内容解析器和一个游标加载器。加载程序用于间接填充listview(即不是一个简单的游标适配器,而是一个数组适配器,因为我需要使用游标的结果来收集其他数据)

当我更改基础数据时,listview不会重新填充,因为不会调用
onLoadFinished(Loader,Cursor)
回调

正如我在写这篇文章时所建议的,在这个问题上有很多问题。 如

所有的问题都指出了两件事:

  • 在contentproviderquery()方法中,您需要告诉光标关于通知的信息
c.setNotificationUri(getContext().getContentResolver(),uri)

  • 在内容提供商插入/更新/删除方法中,您需要通知URI:
getContext().getContentResolver().notifyChange(uri,null)

我在做那些事

我也不会关闭我得到的任何游标

请注意,我的内容提供商位于一个单独的应用程序中(将其视为一个内容提供商应用程序——无启动器主活动)。一个com.example.provider APK,并且com.example.app正在通过content://com.example.provider/table 内容解析器(dbhelper)位于活动链接的库项目(com.example.appdb)中。(这样,多个项目可以通过链接使用dbhelper,所有内容提供商都通过单个APK安装)

我已经在加载程序管理器中打开了调试,可以看到在数据更改后强制刷新的位置(即加载程序被重新启动,而之前的加载程序被标记为非活动),但是没有任何东西表明任何事情是自动发生的,而是响应我的强制刷新

知道为什么我的加载器没有被刷新吗

--编辑--

加载程序将创建:

Log.d(TAG, "onCreateLoader ID: " + loaderID);
// typically a switch on the loader ID, and then 
return dbHelper.getfoo()
其中getfoo()通过以下方式返回光标加载器:

返回新的游标装入器(上下文、FOO_URI、FOO_字段、FOO_查询、FOO_argArray、FOO_排序)

Loader Finish接收光标并填充一个表(并进行一些处理)——没有什么特别之处

public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
    Log.d(TAG, "onLoadFinished id: " + loader.getId());
    // switch on loader ID .. 
    FillTable(cursor, (FooAdapter) foo_info.listview.getAdapter();
然后插入/更新类似于:

public Uri insert(Uri uri, ContentValues initialValues) {
    ContentValues values;
    if (initialValues != null) {
        values = new ContentValues(initialValues);
    } else {
        values = new ContentValues();
    }

    String tableName;
    Uri contentUri;

    switch (sUriMatcher.match(uri)) {
    case FOO:
        tableName = FOOTABLE;
        contentUri = FOO_URI;
        break;

    default:
        throw new IllegalArgumentException("Unknown URI " + uri);
    }

    SQLiteDatabase db = dbHelper.getWritableDatabase();
    long rowId = db.insert(tableName, null, values);
    if (rowId > 0) {
        Uri objUri = ContentUris.withAppendedId(contentUri, rowId);
        getContext().getContentResolver().notifyChange(objUri, null);
        return objUri;
    }

    throw new SQLException("Failed to insert row into " + uri);
}

我发现您没有在onLoadFinished和onLoaderReset中调用swapCursor或changeCursor。您需要这样做,适配器才能访问加载到新游标中的数据

在onLoadFinished中,调用如下内容:

mAdapter.swapCursor(cursor)
在onLoaderReset中,调用此选项以删除对旧光标的引用:

mAdapter.swapCursor(null)
其中mAdapter是listView的适配器


更多信息:

因此,对于查找此信息并遇到此问题的任何人:

确保注册光标的URI与通知光标的URI相同


在我的例子中,我使用的URI与修改基础表的其他代码中使用的URI不同。没有一个简单的修复方法可以让通知生效,所以我一直在重置OnResume()中的加载程序作为解决方案。

这不是对这个特定问题的直接回答,但可能会帮助其他类似情况的人。在我的例子中,我有一个连接,即使我在投影和查询中使用了完整的tablename.columnname。它最终还是使用了错误的ID值。因此,请务必检查ContentProvider或SQL语法。

发布一些与游标加载程序相关的代码可能会有所帮助。主要是onCreateLoader、onLoaderReset和onLoadFinished方法。我假设您的ContentProvider在您刷新时到达notifyChange调用。很抱歉,风暴/断电等让我离开了一段时间。我可能选择了代码中的第一个示例,它是一个阵列适配器,因为我们需要查找光标中或光标所在的数据库中都没有的其他信息(即它位于另一个数据库中,因此我不能在查询中使用联接)。还有其他几个simplecursoradapter(或从简单游标派生的),它们对返回的数据执行
swapCursor()
(也不自动刷新)。您是否使用SimpleCursorAdapter然后查找其他信息?在我看来,您最好使用在适配器类中执行添加查找的自定义适配器。我必须查看调用
swapCursor()
的其他适配器,但不要刷新,因为它们可能有其他问题。
mAdapter.swapCursor(cursor)
mAdapter.swapCursor(null)