Фрагменти, ContentProviders и курсори при промяна на ориентацията

Моля, помогнете ми да разбера какво се случва тук.

Имам два фрагмента (A и B) в раздели, които четат данни от различни таблици, чрез CursorLoader и aContentProvider, в Sqlite-база данни. С различни URI мога да променя към коя таблица ContentProvider прави заявки.

I работи според очакванията, когато превключвам между разделите A и B, освен ако не превключа към B, завъртя и превключа обратно към A, се връща грешен курсор. Курсорът от фрагмент B се връща вместо курсор за фрагмент A, като кара listView във фрагмент A да причини срив. По някакъв начин курсорът изглежда се използва повторно при завъртане.

Защо се случва това и как мога да предотвратя връщането на грешен курсор?

Това е, което имам както във фрагмент А, така и във фрагмент Б. Опитах се да направя идентификационен номер на товарач без успех.

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;

}

person jannej    schedule 24.11.2013    source източник
comment
1. Защо рестартирате Loader в onResume()? При използване на CursorLoader данните се актуализират автоматично. 2. Използвате ли Loaders в Activity? Ако да защо?   -  person Paul Burke    schedule 25.11.2013
comment
1. Хм. Добър въпрос. По принцип следвам този урок: sunil-android.blogspot .se/2013/04/ 2. Не използвам зареждащото средство в дейността, а само стартирам зареждащото средство onCreateView() във всеки фрагмент по следния начин: developer.android.com/training/load-data-background/   -  person jannej    schedule 25.11.2013
comment
Още ли си там? Публикувах отговор.   -  person Paul Burke    schedule 27.11.2013
comment
Съжалявам за отсъствието ми. Мисля, че открих причината за проблемите ми. Фрагментите бяха инициализирани два пъти при завъртане поради savedState в основната дейност (много въпроси относно това тук) и така нататък. Но все пак имате някои валидни точки, които помогнаха в правилната посока. Благодаря.   -  person jannej    schedule 27.11.2013


Отговори (1)


Когато използвате CursorLoader, промените в данните се наблюдават автоматично, така че определено трябва да премахнете извикването restartLoader във вашия onResume(). Ако се внедри правилно, трябва да извикате само initLoader в onActivityCreated от Fragment.

LoaderManager Идентификаторите са обхванати само от Fragment, така че трябва да използвате static constant ID. Ако самите Loaders се обработват в Fragments, напълно е добре всеки Fragment да има един и същ Loader ID (дори ако се управляват от един и същ Activity).

Така че във всеки Fragment:

private static final int LOADER_ID = 0;

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

    // ...

    getLoaderManager().initLoader(LOADER_ID, null, this);
}
person Paul Burke    schedule 25.11.2013