Fragment被replace後視圖被摧毀

在Fragment被replace後再返回,視圖變成了空白

最近在做項目時,發現Fragment在被replace後再返回(在已經addToBackStack的情況下),原來的Fragment視圖變成一片空白。

測試:

  • Fragment一共有11個生命週期,我把Fragment的生命週期過程全都打一遍Log

    public class fragment1 extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
      View view = inflater.inflate(R.layout.aaaa, container, false);
      Log.d("fragmentLife", "onCreateView");
        return view;
    }
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      Log.d("fragmentLife", "onCreate");
    }
    
    @Override
    public void onAttach(Activity activity) {
      Log.d("fragmentLife", "onAttach");
      super.onAttach(activity);
    }
    
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
      Log.d("fragmentLife", "onActivityCreated");
      super.onActivityCreated(savedInstanceState);
    }
    
    @Override
    public void onStart() {
      Log.d("fragmentLife", "onStart");
      super.onStart();
    }
    
    @Override
    public void onResume() {
      Log.d("fragmentLife", "onResume");
      super.onResume();
    }
    
    @Override
    public void onPause() {
      Log.d("fragmentLife", "onPause");
      super.onPause();
    }
    
    @Override
    public void onStop() {
      Log.d("fragmentLife", "onStop");
      super.onStop();
    }
    
    @Override
    public void onDestroy() {
      Log.d("fragmentLife", "onDestroy");
      super.onDestroy();
    }
    
      @Override
      public void onDestroyView() {
      Log.d("fragmentLife", "onDestroyView");
      super.onDestroyView();
    }
    
    @Override
    public void onDetach() {
      Log.d("fragmentLife", "onDetach");
      super.onDetach();
    }
    } 
    
  • 然後在Activity中先add再replace,然後再返回,最後退出

    int i = 0;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
    
      Log.d("fragmentLife", "添加");
      getFragmentManager().beginTransaction()
      .add(R.id.container, new fragment1())
      .commit();
    
      Button button = (Button)findViewById(R.id.button1);
      button.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            Log.d("fragmentLife", "替換");
            getFragmentManager().beginTransaction()
            .replace(R.id.container, new fragment2())
            .addToBackStack(null)
            .commit();  
        }
    });
    }
    
    @Override
    public void onBackPressed() {
        i++;
    if(i==1){
        Log.d("fragmentLife", "返回");
    }else{
      Log.d("fragmentLife", "退出程序");
        }
      super.onBackPressed();
    }
    
  • 我們來看一下Log日誌

    D/fragmentLife(2440): 添加
    D/fragmentLife(2440): onAttach
    D/fragmentLife(2440): onCreate
    D/fragmentLife(2440): onCreateView
    D/fragmentLife(2440): onActivityCreated
    D/fragmentLife(2440): onStart
    D/fragmentLife(2440): onResume
    D/fragmentLife(2440): 替換
    D/fragmentLife(2440): onPause
    D/fragmentLife(2440): onStop
    D/fragmentLife(2440): onDestroyView
    D/fragmentLife(2440): 返回
    D/fragmentLife(2440): onCreateView
    D/fragmentLife(2440): onActivityCreated
    D/fragmentLife(2440): onStart
    D/fragmentLife(2440): onResume
    D/fragmentLife(2440): 退出程序
    D/fragmentLife(2440): onPause
    D/fragmentLife(2440): onStop
    D/fragmentLife(2440): onDestroyView
    D/fragmentLife(2440): onDestroy
    D/fragmentLife(2440): onDetach
    

看出問題: Fragment已經addToBackStack,在被replace後,雖然Fragment實例沒有被摧毀,但是會回調onDestroyView()方法,導致視圖被摧毀。

解決方法: 定義一個boolean變量,在onCreateView方法中判斷此boolean的值,決定是否恢復視圖。

  • 1.定義一個boolean變量

    private boolean isViewDetroy;
    
  • 2.在onCreate方法中初始化isViewDetroy = false;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        returView = false;
    }
    
  • 3.在Fragment的onDestroyView方法中讓isViewDetroy = true;

    @Override
    public void onDestroyView() {
       super.onDestroyView();
       isViewDetroy = true;
    }
    
  • 4.在onCreatView方法中判斷isViewDetroy,如果爲true,則恢復視圖

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragmen,container,false);
    
       if(isViewDetroy = true){
           ......  //此處執行恢復視圖操作
        }
        return view;
    }
    

謝謝!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章