【问题标题】:Fragments, ContentProviders and cursors on orientation change方向改变时的片段、ContentProviders 和光标
【发布时间】:2013-11-25 20:26:31
【问题描述】:

请帮助我了解这里发生了什么。

我在 Sqlite 数据库中通过 CursorLoader 和 aContentProvider 从不同表读取数据的选项卡中有两个片段(A 和 B)。使用不同的 URI,我可以更改 ContentProvider 正在查询的表。

在选项卡 A 和 B 之间切换时,我按预期工作,除非我切换到 B,旋转并切换回 A,否则会返回错误的光标。返回来自片段 B 的光标而不是片段 A 的光标,这会使片段 A 中的 listView 导致崩溃。在某种程度上,光标似乎在旋转时被重用。

为什么会发生这种情况,如何防止返回错误的光标?

这是我在片段 A 和 B 中的内容。尝试分配加载程序 ID 没有成功。

public void onResume() {
    super.onResume();
    getLoaderManager().restartLoader(mLoaderId, null, this);
}

我的 ContentProvider 如下所示:

public Cursor query(Uri uri, String[] projection, String selection,
        String[] selectionArgs, String sortOrder) {

    SQLiteDatabase db = dbHelper.getWritableDatabase();
    SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();

    Cursor cursor = null;       

    switch (uriMatcher.match(uri)) {
    case ALL_NEWS:
        queryBuilder.setTables(NewsDb.SQLITE_TABLE);
        cursor = queryBuilder.query(db, projection, selection,
                selectionArgs, null, null, sortOrder);
        break;

    case SINGLE_PLACE:
        queryBuilder.setTables(PlacesDb.SQLITE_TABLE);
        String id = uri.getPathSegments().get(1);
        queryBuilder.appendWhere(PlacesDb.KEY_ID + "=" + id);
        cursor = queryBuilder.query(db, projection, selection,
                selectionArgs, null, null, sortOrder);
        break;

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


    return cursor;

}

【问题讨论】:

  • 1.为什么要重启onResume() 中的Loader?使用CursorLoader 时,数据会自动更新。 2、你是用Activity中的Loaders吗?如果有,为什么?
  • 1.嗯。好问题。我基本上正在关注本教程:sunil-android.blogspot.se/2013/04/… 2. 我没有在 Activity 中使用加载器,只在每个片段中初始化加载器 onCreateView(),如下所示:developer.android.com/training/load-data-background/…
  • 你还在吗?我已经发布了答案。
  • 抱歉我的缺席。我想我已经找到了导致我的问题的原因。由于主活动中的已保存状态而在旋转时初始化两次的片段(这里有很多关于此的问题)等等。但是您仍然有一些有效的观点有助于朝着正确的方向发展。谢谢。

标签: android android-contentprovider android-orientation android-cursorloader


【解决方案1】:

使用CursorLoader 时,会自动观察数据变化,因此您一定要删除onResume() 中的restartLoader 调用。如果实施得当,您应该只需要在FragmentonActivityCreated 中调用initLoader

LoaderManager ID 仅限于Fragment,因此您应该使用static constant ID。如果Loaders Fragments 中处理,那么每个Fragment 都可以拥有相同的Loader ID(即使它们由相同的@987654334 管理) @)。

所以在每个Fragment:

private static final int LOADER_ID = 0;

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    // ...

    getLoaderManager().initLoader(LOADER_ID, null, this);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多