Google 建议我们getLoaderManager().initLoader(0, null, this);
在 Fragment 的onActivityCreated
http://developer.android.com/reference/android/content/AsyncTaskLoader.html
但是,这会产生以下问题:onLoadFinished 在配置更改期间将被调用两次(轮换)
我们可以模拟如下问题。
代码
package org.yccheok.gui;
import android.content.Context;
import android.os.Bundle;
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;
import com.actionbarsherlock.app.SherlockFragment;
public class HomeMenuFragment extends SherlockFragment implements LoaderManager.LoaderCallbacks<HomeMenuFragment.Infos> {
private static class InfosLoader extends AsyncTaskLoader<Infos> {
private Infos infos = null;
public InfosLoader(Context context) {
super(context);
}
@Override
public Infos loadInBackground() {
Log.i(TAG, "loadInBackground");
this.infos = Infos.newInstance();
return infos;
}
/**
* Handles a request to cancel a load.
*/
@Override
public void onCanceled(Infos infos) {
super.onCanceled(infos);
}
/**
* 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.infos != null) {
Log.i(TAG, "deliverResult");
deliverResult(this.infos);
}
if (takeContentChanged() || this.infos == null) {
Log.i(TAG, "forceLoad");
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.infos = null;
}
}
static class Infos {
private Infos() {
}
public static Infos newInstance() {
return new Infos();
}
}
@Override
public void onActivityCreated (Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.i(TAG, "onActivityCreated");
// Prepare the loader. Either re-connect with an existing one,
// or start a new one.
getLoaderManager().initLoader(0, null, this);
}
@Override
public Loader<Infos> onCreateLoader(int arg0, Bundle arg1) {
return new InfosLoader(this.getSherlockActivity());
}
@Override
public void onLoadFinished(Loader<Infos> arg0, Infos arg1) {
Log.i(TAG, "onLoadFinished! -> " + arg1);
}
@Override
public void onLoaderReset(Loader<Infos> arg0) {
}
public void reloadAfterOpenFromCloud() {
this.getLoaderManager().getLoader(0).onContentChanged();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.home_menu, container, false);
return v;
}
private static final String TAG = HomeMenuFragment.class.getSimpleName();
}
日志记录
I/HomeMenuFragment(14776): onActivityCreated
I/HomeMenuFragment(14776): forceLoad
I/HomeMenuFragment(14776): loadInBackground
I/HomeMenuFragment(14776): onLoadFinished! -> org.yccheok.gui.HomeMenuFragment$Infos@4195ad58
[Rotation happens right here]
I/HomeMenuFragment(14776): onActivityCreated
I/HomeMenuFragment(14776): onLoadFinished! -> org.yccheok.gui.HomeMenuFragment$Infos@4195ad58
I/HomeMenuFragment(14776): onLoadFinished! -> org.yccheok.gui.HomeMenuFragment$Infos@4195ad58
根据Android: LoaderCallbacks.OnLoadFinished 调用了两次,建议的解决方案之一是调用initLoader
。onResume
@Override
public void onActivityCreated (Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.i(TAG, "onActivityCreated");
//getLoaderManager().initLoader(0, null, this);
}
@Override
public void onResume()
{
super.onResume();
Log.i(TAG, "onResume");
// Prepare the loader. Either re-connect with an existing one,
// or start a new one.
getLoaderManager().initLoader(0, null, this);
}
这是日志记录。现在我们搬到. initLoader
_onResume
日志记录
I/HomeMenuFragment(15468): onActivityCreated
I/HomeMenuFragment(15468): onResume
I/HomeMenuFragment(15468): forceLoad
I/HomeMenuFragment(15468): loadInBackground
I/HomeMenuFragment(15468): onLoadFinished! -> org.yccheok.gui.HomeMenuFragment$Infos@4195aed0
I/HomeMenuFragment(15468): onActivityCreated
I/HomeMenuFragment(15468): onResume
I/HomeMenuFragment(15468): onLoadFinished! -> org.yccheok.gui.HomeMenuFragment$Infos@4195aed0
我想知道
- 为什么建议的解决方案有效?
- 这是一个错误吗?我们是否应该向 Google 提交有关此行为的错误?也许有人向 Google 提交了一张罚单,但我找不到。