Согласно http://developer.android.com/guide/components/loaders.html, одна из приятных вещей о загрузчике заключается в том, что она может сохранять свои данные во время изменения конфигурации.
Они автоматически подключаются к последнему курсору загрузчика, когда воссоздан после изменения конфигурации. Таким образом, им не нужно повторно запросить их данные.
Однако во всех сценариях он не работает.
Я делаю следующий простой пример. Это FragmentActivity
, в котором размещается Fragment
. Fragment
сам принадлежит AsyncTaskLoader
.
Следующие 3 сценария работают очень хорошо.
Во время первого запуска (OK)
Создается1 загрузчик, а loadInBackground
выполняется один раз.
Во время простого вращения (OK)
Никакой новый загрузчик не создается и loadInBackground
не запускается.
Запускается дочерняя активность и нажата кнопка возврата (ОК)
Никакой новый загрузчик не создается и loadInBackground
не запускается.
Однако в следующем сценарии.
Запущена дочерняя активность → Вращение → нажата кнопка "Назад" (Неверно)
В это время вызывается старый загрузчик onReset
. Старый загрузчик будет уничтожен. Будет создан новый загрузчик, и новый загрузчик loadInBackground
будет запущен снова.
Правильное поведение, которое я ожидаю, не будет создан новый загрузчик.
Код, связанный с загрузчиком, следующий. Я запускаю код под эмулятором Android 4.1.
package com.example.bug;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.content.Loader;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class MainFragment extends Fragment implements LoaderManager.LoaderCallbacks<Integer> {
private static class IntegerArrayLoader extends AsyncTaskLoader<Integer> {
private Integer result = null;
public IntegerArrayLoader(Context context) {
super(context);
Log.i("CHEOK", "IntegerArrayLoader created!");
}
@Override
public Integer loadInBackground() {
Log.i("CHEOK", "Time consuming loadInBackground!");
this.result = 123456;
return result;
}
/**
* Handles a request to cancel a load.
*/
@Override
public void onCanceled(Integer integer) {
super.onCanceled(integer);
}
/**
* Handles a request to stop the Loader.
* Automatically called by LoaderManager via stopLoading.
*/
@Override
protected void onStopLoading() {
// Attempt to cancel the current load task if possible.
cancelLoad();
}
/**
* Handles a request to start the Loader.
* Automatically called by LoaderManager via startLoading.
*/
@Override
protected void onStartLoading() {
if (this.result != null) {
deliverResult(this.result);
}
if (takeContentChanged() || this.result == null) {
forceLoad();
}
}
/**
* Handles a request to completely reset the Loader.
* Automatically called by LoaderManager via reset.
*/
@Override
protected void onReset() {
super.onReset();
// Ensure the loader is stopped
onStopLoading();
// At this point we can release the resources associated with 'apps'
// if needed.
this.result = null;
}
}
@Override
public Loader<Integer> onCreateLoader(int arg0, Bundle arg1) {
Log.i("CHEOK", "onCreateLoader being called");
return new IntegerArrayLoader(this.getActivity());
}
@Override
public void onLoadFinished(Loader<Integer> arg0, Integer arg1) {
result = arg1;
}
@Override
public void onLoaderReset(Loader<Integer> arg0) {
// TODO Auto-generated method stub
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_main, container, false);
return v;
}
// http://stackoverflow.com/info/11293441/android-loadercallbacks-onloadfinished-called-twice
@Override
public void onResume()
{
super.onResume();
if (result == null) {
// Prepare the loader. Either re-connect with an existing one,
// or start a new one.
getLoaderManager().initLoader(0, null, this);
} else {
// Restore from previous state. Perhaps through long pressed home
// button.
}
}
private Integer result;
}
Полный исходный код можно загрузить с https://www.dropbox.com/s/n2jee3v7cpwvedv/loader_bug.zip
Это может быть связано с 1 неизвестной ошибкой Android: https://code.google.com/p/android/issues/detail?id=20791&can=5&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars
https://groups.google.com/forum/?fromgroups=#!topic/android-developers/DbKL6PVyhLI
Мне было интересно, есть ли хорошие способы обхода этой ошибки?