如何让Fragment的切换优雅些?

4,015 阅读1分钟

Fragment切换生命周期变化

  • 通过add、hide、show切换Fragment切换时不执行Fragment生命周期,调用onHiddenChanged方法
  • 通过replace切换Fragment切换时,Fragment都进行了销毁,重建的过程。相当于执行了一次生命周期

执行replace用 fragment2 替换 fragment1

  • fragment1:onPause() -> onStop() -> onDestroyView() -> onDestroy() -> onDetach()
  • fragment2:onAttach() -> onCreate() -> onCreateView() -> onActivityCreated() -> onStart() -> onResume()
  • 通过ViewPager切换Fragment切换时不执行生命周期,调用setUserVisibleHint方法

切换Fragment

  • 通过replace切换Fragment,每次都会经历Fragment的销毁与重建

这种做法比较消耗性能,特别是在Fragment中有大量的网络请求时,给用户的体验也不好

    private void showFragment(Fragment fragment) {
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.replace(R.id.layout_content, fragment);
        transaction.commit();
    }
  • 通过add、hide、show来切换Fragment
    /**
     * 修改显示的内容,不会销毁与重建
     * to 要切换的fragment
     * mCurrent 当前fragment
     */
    private void switchContent(Fragment to) {
    	FragmentTransaction transaction = fragmentManager.beginTransaction();
        if (mCurrent !=null && mCurrent != to) {
            if (!to.isAdded()) { // 判断是否被add过
                // 隐藏当前的fragment,将 下一个fragment 添加进去
      		transaction.hide(mCurrent).add(R.id.ft_content, to).commit(); 
            } else {
                // 隐藏当前的fragment,显示下一个fragment
              	transaction.hide(mCurrent).show(to).commit(); 
            }
            mCurrent = to;
        }
       }else if(mCurrent == null){
    	    mCurrent = to;
            if(!to.isAdded()){
                transaction.add(R.id.ft_content, to).commit(); 
            }else{
                transaction.show(to).commit(); 
            }
       }
   }

通过该方式切换Fragment不会回调生命周期方法,需要通过onHiddenChanged回调实现逻辑

    @Override
    public void onHiddenChanged(boolean hidden) {
        super.onHiddenChanged(hidden);
        if (hidden) { // fragment不显示,相当于调用了onPause();
            return;
        }else{  // fragment显示,相当于调用了onResume();
           // 可以做一些网络数据刷新逻辑等。。。
        }
    }