Android - Retain objects in UI Fragment

前端 未结 1 1822
遥遥无期
遥遥无期 2021-01-22 12:51

In my project, I originally use this scheme:

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

相关标签:
1条回答
  • 2021-01-22 13:34

    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;
        }
    
    }
    

    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
            }
        }
    
    }
    

    And in retain.task.onPostExecute():

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

    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();
    }
    
    0 讨论(0)
提交回复
热议问题