Android - 在 UI 片段中保留对象 [英] Android - Retain objects in UI Fragment

查看:18
本文介绍了Android - 在 UI 片段中保留对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的项目中,我最初使用这个方案:

In my project, I originally use this scheme:

Activity A (UI) > Fragment B (non-UI) > Adapter + AsyncTask

Activity A (UI) > Fragment B (non-UI) > Adapter + AsyncTask

  • B 保留与 setRetainInstance(true) 并更新 A UI
  • A 使用 getFragmentManager()
  • 实例化 B

    • B retained with setRetainInstance(true) and updating A UI
    • A instantiate B with getFragmentManager()
    • 但是我现在需要使用UI Fragments,所以我想使用这个方案:

      But I now need to use UI Fragments, so I thought to use this scheme:

      Activity A > Fragment B (UI) > Fragment C (非 UI) > Adapter + AsyncTask

      Activity A > Fragment B (UI) > Fragment C (non-UI) > Adapter + AsyncTask

      • C 保留了 setRetainInstance(true) 并更新了 B UI
      • B 使用 getChildFragmentManager()
      • 实例化 C

        • C retained with setRetainInstance(true) and updating B UI
        • B instantiate C with getChildFragmentManager()
        • 但似乎不可能:

          Caused by: java.lang.IllegalStateException:
              Can't retain fragements that are nested in other fragments
          

          我尝试使用 getFragmentManager() 而不是 getChildFragmentManager() 来实例化 C 但我遇到了一些问题.

          I tried to instantiate C with getFragmentManager() instead of getChildFragmentManager() but I had some problems.

          在 Fragment 中保留对象和管理 AsyncTask 的最佳做法是什么?

          What is the best practice to retain objects and manage AsyncTasks in a Fragment?

          推荐答案

          我终于开发了一个小助手类:

          I finally develop a little helper class:

          public class RetainFragment<F extends Fragment> extends Fragment {
          
              private static <F extends Fragment> String tag(F ui, Object id) {
                  return ui.getClass().getName() + id.toString();
              }
          
              public static <F extends Fragment> Fragment get(F ui, Object id) {
                  return ui.getFragmentManager().findFragmentByTag(tag(ui, id));
              }
          
              public F ui;
              public Object id;
          
              @Override
              public void onCreate(Bundle state) {
                  super.onCreate(state);
                  setRetainInstance(true);
              }
          
              public void link(F ui, Object id) {
                  this.id = id;
                  this.ui = ui;
                  if (get(ui, id) == null) {
                      ui.getFragmentManager()
                        .beginTransaction()
                        .add(this, tag(ui, id))
                        .commit();
                  }
              }
          
              public void unlink() {
                  if (get(ui, id) != null) {
                      ui.getFragmentManager()
                        .beginTransaction()
                        .remove(this)
                        .commit();
                  }
                  ui = null;
                  id = null;
              }
          
          }
          

          现在,在 UI Fragments 中,我只写:

          And now, in UI Fragments, I only write:

          public class UiFragment extends Fragment {
          
              private static class Retain extends RetainFragment<UiFragment> {
                  private MyAsyncTask task;   // Objects to retain over
                  private MyAdapter adapter;  // configuration changes
              }
          
              private Retain retain;
          
              @Override
              public void onAttach(Activity activity) {
                  super.onAttach(activity);
                  retain = (Retain) Retain.get(this, 0);
                  if (retain == null) {
                      retain = new Retain();
                      // Retained objects initialization
                      retain.adapter = new MyAdapter();
                  }
                  retain.link(this, 0);
              }
          
              @Override
              public void onDetach() {
                  if (isRemoving()) {
                      // Retained objects terminate
                      if (retain.task != null) {
                          retain.task.cancel(true);
                      }
                      retain.unlink();
                  }
                  super.onDetach();
              }
          
              private void update() {
                  if (!isDetached()) {
                      // Update UI fragment
                  }
              }
          
          }
          

          retain.task.onPostExecute()中:

          retain.ui.update(); // Reference to the last ui fragment instance linked
          

          并在 UI 片段启动时启动任务:

          And to launch the task at UI fragment startup:

          private static class Retain extends RetainFragment<UiFragment> {
              private MyAsyncTask task;   // Objects to retain over
              private MyAdapter adapter;  // configuration changes
          
              @Override
              public void onCreate(Bundle state) {
                  super.onCreate(state);
                  ui.onRetainCreated();
              }
          }
          
          private void onRetainCreated() {
              retain.task = new MyAsyncTask() {
                  @Override
                  protected void onPostExecute(Void result) {
                      retain.ui.update();
                  }
              };
              retain.task.execute();
          }
          

          这篇关于Android - 在 UI 片段中保留对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆