You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多CursorAdapter适配不同Fragment仅一个生效,RecipeCursorAdapter报错求助

解决多个CursorAdapter适配不同Fragment的异常问题

从你的报错日志和代码来看,核心问题是**RecipeCursorAdapter拿到的Cursor并不属于recipes表**——日志里getColumnIndex(RecipeEntry.COLUMN_RECIPE_SERVINGS)返回了-1,说明这个Cursor里根本没有这个列,结合你怀疑的点,大概率是给RecipeCursorAdapter传入了查询store表得到的Cursor,导致访问不存在的列抛出异常。

下面是一步步的排查和解决方法:

1. 确认Cursor的来源是否正确

首先检查你创建RecipeCursorAdapter的地方(比如对应的RecipeFragment的Loader回调里),确保查询的是recipes表的Uri,而不是store表的:

比如在RecipeFragment的LoaderManager.LoaderCallbacks<Cursor>实现中,onCreateLoader方法应该是这样的:

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    // 只查询recipes表需要的列
    String[] projection = {
        RecipeEntry._ID,
        RecipeEntry.COLUMN_RECIPE_NAME,
        RecipeEntry.COLUMN_RECIPE_TYPE,
        RecipeEntry.COLUMN_RECIPE_SERVINGS,
        RecipeEntry.COLUMN_RECIPE_VALUES
    };
    // 必须使用RecipeEntry的CONTENT_URI,而不是StoreEntry的
    return new CursorLoader(getContext(),
            RecipeEntry.CONTENT_URI,
            projection,
            null,
            null,
            null);
}

如果这里误用了StoreEntry.CONTENT_URI,就会拿到store表的Cursor,自然找不到recipes表的列。

2. 检查ContentProvider的query逻辑

确认你的ContentProvider中,针对RecipeEntry.CONTENT_URI的查询,确实返回的是recipes表的数据:

@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    SQLiteDatabase db = mDbHelper.getReadableDatabase();
    Cursor cursor;
    int match = sUriMatcher.match(uri);
    
    switch (match) {
        // 确保RECIPES匹配的是RecipeEntry的Uri
        case RECIPES:
            cursor = db.query(
                RecipeEntry.TABLE_NAME,  // 这里必须是recipes表的表名常量
                projection,
                selection,
                selectionArgs,
                null,
                null,
                sortOrder);
            break;
        case STORES:
            cursor = db.query(StoreEntry.TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder);
            break;
        // 其他匹配分支...
        default:
            throw new IllegalArgumentException("无法查询未知URI: " + uri);
    }
    
    cursor.setNotificationUri(getContext().getContentResolver(), uri);
    return cursor;
}

同时要确认UriMatcher的规则是正确的,比如:

private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static {
    sUriMatcher.addURI(CONTENT_AUTHORITY, RecipeEntry.PATH_RECIPES, RECIPES);
    sUriMatcher.addURI(CONTENT_AUTHORITY, StoreEntry.PATH_STORES, STORES);
}

保证Recipe的Uri能正确匹配到RECIPES分支,查询正确的表。

3. 验证列名常量的正确性

检查RecipeEntry里的列名常量是否和数据库创建时的列名完全一致,比如:

public static final String COLUMN_RECIPE_SERVINGS = "recipe_servings";

要确保这个字符串和你创建recipes表时写的列名完全相同,没有拼写错误(比如大小写、多/少字母)。

4. 额外调试技巧

如果还是不确定问题,可以在RecipeCursorAdapter的bindView方法里打印Cursor的所有列名,直接验证Cursor属于哪个表:

// 在bindView开头添加这段代码
for (int i = 0; i < cursor.getColumnCount(); i++) {
    Log.e(LOG_TAG, "当前Cursor的列名: " + cursor.getColumnName(i));
}

如果打印出来的是store表的列(比如product_name、product_price等),那就实锤是传错了Cursor,回到步骤1和2修正即可。

按照上面的步骤排查后,RecipeCursorAdapter应该能正确访问recipes表的数据,和PlatformCursorAdapter各自正常工作。

内容的提问来源于stack exchange,提问作者Wissam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:04:39