【发布时间】:2011-08-15 14:38:36
【问题描述】:
我有 1 个活动和 2 个片段。两个片段都使用自定义 AsyncTaskLoader 从 Web 服务获取一些数据,并且当我使用 Loader 时,它应该跨活动和片段重新创建保留数据。两个片段都会覆盖 onActivityCreated 方法并调用 getLoaderManager().initLoader(0, null, this) 来创建新的或重用现有的加载器。
Activity 首次创建时,默认在 FrameLayout 中添加 Fragment #1,加载数据,内部调用 LoaderCallbacks.onLoadFinished() 方法并显示结果。我有一个按钮,它在单击时用 Fragment #2 替换 Fragment #1,并且 Fragment #1 被推送到 Fragment-backstack。当用户按下 BACK 键时,它会切换回 Fragment #1。
onActivityCreated 在 Fragment #1 上再次被调用,然后显然再次调用 iniLoader()。这次数据已经存在于加载器中,我希望它再次自动调用 LoaderCallbacks.onLoadFinished 方法,因为它已经有可用的数据,如下所述:http://goo.gl/EGFJk
确保加载程序已初始化并处于活动状态。如果加载器尚不存在,则创建一个并(如果活动/片段当前已启动)启动加载器。否则,最后创建的加载器将被重新使用。 在任何一种情况下,给定的回调都与加载程序相关联,并将在加载程序状态更改时调用。 如果在调用点调用者处于启动状态,并且请求的加载器已经存在并且已经生成了它的数据,那么回调 onLoadFinished(Loader, D) 将立即被调用(在这个函数内部),所以你必须为此做好准备。
但是,即使加载器存在并且已经生成了可以交付的数据,该方法也不会被调用。
编辑 #1 用户角度的问题:
- 用户启动活动并看到带有一些数据的 fragment1
- 用户单击某项将第一个片段更改为另一个片段,具有不同的 数据
- 用户点击返回键
- 用户现在再次查看 fragment1,但没有数据。 (这意味着我需要再次从网络服务中获取它——如果可能的话,我想避免这种情况)
这是我的活动:
public class FragmentTestsActivity extends Activity implements OnClickListener {
private Button btn1;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn1 = (Button) findViewById(R.id.btn1);
btn1.setOnClickListener(this);
Fragment newFragment = new Fragment1();
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.add(R.id.fragmentContainer, newFragment).commit();
}
@Override
public void onClick(View view) {
int id = view.getId();
if (id == R.id.btn1) {
showNewFragment();
}
}
public void showNewFragment() {
// Instantiate a new fragment.
Fragment2 newFragment = new Fragment2();
// Add the fragment to the activity, pushing this transaction
// on to the back stack.
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.fragmentContainer, newFragment);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);
ft.commit();
}
}
我的片段#1:
public class Fragment1 extends Fragment implements LoaderCallbacks<String> {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment1, container, false);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
LoaderManager.enableDebugLogging(true);
getLoaderManager().initLoader(0, null, this);
}
private static class TestLoader extends AsyncTaskLoader<String> {
String result;
public TestLoader(Context context) {
super(context);
}
@Override
public String loadInBackground() {
// Some long-running call to a webservice - replaced with a simple string to test with
return "FirstTimeData";
}
@Override
public void deliverResult(String data) {
result = data;
if (isStarted()) {
super.deliverResult(data);
}
}
@Override
protected void onStartLoading() {
if (result != null) {
deliverResult(result);
}
if (takeContentChanged() || result == null) {
forceLoad();
}
}
@Override
protected void onStopLoading() {
cancelLoad();
}
}
@Override
public Loader<String> onCreateLoader(int id, Bundle args) {
return new TestLoader(getActivity());
}
@Override
public void onLoadFinished(Loader<String> loader, String result) {
Log.d("Fragment1", "onLoadFinished: " + result);
}
@Override
public void onLoaderReset(Loader<String> loader) {
// TODO Auto-generated method stub
}
}
任何人都知道这个问题的解决方案或我在这里做错了什么?非常感谢任何帮助。
【问题讨论】:
标签: java android android-fragments