How to correctly save instance state of Fragments in back stack?

后端 未结 6 1268
小鲜肉
小鲜肉 2020-11-21 11:57

I have found many instances of a similar question on SO but no answer unfortunately meets my requirements.

I have different layouts for portrait and landscape and I

6条回答
  •  爱一瞬间的悲伤
    2020-11-21 12:22

    This is the way I am using at this moment... it's very complicated but at least it handles all the possible situations. In case anyone is interested.

    public final class MyFragment extends Fragment {
        private TextView vstup;
        private Bundle savedState = null;
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View v = inflater.inflate(R.layout.whatever, null);
            vstup = (TextView)v.findViewById(R.id.whatever);
    
            /* (...) */
    
            /* If the Fragment was destroyed inbetween (screen rotation), we need to recover the savedState first */
            /* However, if it was not, it stays in the instance from the last onDestroyView() and we don't want to overwrite it */
            if(savedInstanceState != null && savedState == null) {
                savedState = savedInstanceState.getBundle(App.STAV);
            }
            if(savedState != null) {
                vstup.setText(savedState.getCharSequence(App.VSTUP));
            }
            savedState = null;
    
            return v;
        }
    
        @Override
        public void onDestroyView() {
            super.onDestroyView();
            savedState = saveState(); /* vstup defined here for sure */
            vstup = null;
        }
    
        private Bundle saveState() { /* called either from onDestroyView() or onSaveInstanceState() */
            Bundle state = new Bundle();
            state.putCharSequence(App.VSTUP, vstup.getText());
            return state;
        }
    
        @Override
        public void onSaveInstanceState(Bundle outState) {
            super.onSaveInstanceState(outState);
            /* If onDestroyView() is called first, we can use the previously savedState but we can't call saveState() anymore */
            /* If onSaveInstanceState() is called first, we don't have savedState, so we need to call saveState() */
            /* => (?:) operator inevitable! */
            outState.putBundle(App.STAV, (savedState != null) ? savedState : saveState());
        }
    
        /* (...) */
    
    }
    

    Alternatively, it is always a possibility to keep the data displayed in passive Views in variables and using the Views only for displaying them, keeping the two things in sync. I don't consider the last part very clean, though.

提交回复
热议问题