android viewpager使用Fragment懶載入,滑到當前fragment才進行資料載入

醜小鴨是白天鵝發表於2017-06-26

前言:如果不做fragment的懶載入則每次進入activity就會初始化沒必要的資料,消耗記憶體和網路流量,再每次自動銷燬後也需要重新初始化fragment的資料,為此優化,我們要做fragment的懶載入,網路上關於懶載入的文章數不勝數,可是詳細、全面,又有實際原始碼和例子的很少,下面是我摘抄的技術程式碼,原文地址見文章下面.
PagerFragment裡面適配的fragment只需要繼承自LazyFragment處理懶載入關係,而LazyFragment繼承自BaseFragment,BaseFragment處理fragment初始化控制元件和fragment銷燬時和activity分離的事情
下面獻上LazyFragment的原始碼:

public class LazyFragment extends BaseFragment
{
    private boolean isInit=false;//真正要顯示的view是否已經被初始化(正常載入)
    private Bundle savedInstancseState;
    public static final String INTENT_BOOLEAN_LAZYLOAD="intent_boolean_lazyLoad";
    private boolean isLazyLoad=true;//預設狀態需要懶載入
    private FrameLayout layout;
    private boolean isStart=false;// 是否處於可見狀態,in the screen
    @override 
    protected final void onCreateView(Bundle savedInstancseState)
    {
        super.onCreateView(savedInstancseState);
        Bundle bundle=getArguments();
        if(bundle!=null)
        {
            isLazyLoad=bundle.getBoolean(INTENT_BOOLEAN_LAZYLOAD,isLazyLoad);
        }
        //判斷是否懶載入 
        if(isLazyLoad)
        { 
            //一旦isVisibleToUser==true即可對真正需要的顯示內容進行載入
            if(getUserVisibleHint()&&!isInint)
            {
                this.savedInstancseState=savedInstancseState;
                onCreateViewLazy(savedInstancseState);
                isInint=true;
            }else{
                 //進行懶載入
                 layout=new FrameLayout(getApplicationContext);
                 layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));
                 View view=LayoutInflater.from(getApplicationContext()).inflate(R.layout.fragment_lazy_loading,null);
                 layout.addView(view);
                 super.setContentView(layout);
            }
        }else
        {
             //不需要懶載入,開門見山,呼叫onCreateViewLazy正常載入顯示內容即可
             onCreateViewLazy(savedInstancseState);
             isInint=true;
        }
    }
    @override
    public void setUserVisibleHint(boolean isVisibleToUser)
    {
       super.setUserVisibleHint(isVisibleToUser);
       Log.d("TAG", "setUserVisibleHint() called with: " + "isVisibleToUser = [" + isVisibleToUser + "]");
       //一旦isVisibleToUser==true即可進行對真正需要的顯示內容的載入
       //可見,但還沒被初始化
       if(isVisibleToUser&&!isInint&&getContentView()!=null)
       {
           onCreateViewLazy(savedInstancseState);
           isInint=true;
           onResumeLazy();//TODO 
       }
       //已經被初始化(正常載入)過了
       if(isInint&&getContentView!=null)
       {
          if(isVisibleToUser)
          {
             isStart=true;
             onFragmentStartLazy();//TODO
          }else{
              isStart=false;
              onFragmentStopLazy();
          }
       }
       @override
       public void setContentView(int layoutResID)
       {
           //判斷若isLazyLoad=true,移除所有lazy view,載入真正要顯示的view
           if(isLazyLoad&&getContentView()!=null&&getContentView().getParent()!=null)
           {
                layout.removeAllViews();
                View view=inflater.inflate(layoutResID,layout,false);
                layout.addView(view);
           }else
           {
               super.setContentView(layoutResID);
           }
       }
       @override
       public void setContentView(View view)
       {
           //判斷若isLazyLoad=true,移除所有lazy view,載入真正要顯示的view
           if(isLazyLoad&&getContentView()!=null&&getContentView().getParent!=null)
           {
              layout.removeAllViews();
              layout.addView(view);
           }else
           {
               //否則開門見山,直接載入
               super.setContentView(view);
           }
       }
       @override
       public final void onStart()
       {
             Log.d("TAG", "onStart() : " + "getUserVisibleHint():" + getUserVisibleHint());
             super.onStart();
             if(isInit&&!isStart&&getUserVisibleHint())
             {
                isStart=true;
                onFragmentStartLazy();
             }
       }
    //當Fragment被滑到可見的位置時,呼叫
    protected void onFragmentStartLazy() {
        Log.d("TAG", "onFragmentStartLazy() called with: " + "");
    }

        @override
        public final void onStop()
        {
           super.onStop();
           if(isInit&&isStart&&getUserVisibleHint())
           {
              isStart=false;
              onFragmentStopLazy();
           }
        }
         @Override
    @Deprecated
    public final void onResume() {
        Log.d("TAG", "onResume() : " + "getUserVisibleHint():" + getUserVisibleHint());
        super.onResume();
        if (isInit) {
            onResumeLazy();
        }
    }
     @Override
    @Deprecated
    public final void onResume() {
        Log.d("TAG", "onResume() : " + "getUserVisibleHint():" + getUserVisibleHint());
        super.onResume();
        if (isInit) {
            onResumeLazy();
        }
    }

    @Override
    @Deprecated
    public final void onPause() {
        Log.d("TAG", "onPause() : " + "getUserVisibleHint():" + getUserVisibleHint());
        super.onPause();
        if (isInit) {
            onPauseLazy();
        }
    }
     @Override
    @Deprecated
    public final void onDestroyView() {
        Log.d("TAG", "onDestroyView() : " + "getUserVisibleHint():" + getUserVisibleHint());
        super.onDestroyView();
        if (isInit) {
            onDestroyViewLazy();
        }
        isInit = false;
    }

     //當Fragment被滑到不可見的位置,offScreen時,呼叫
    protected void onFragmentStopLazy() {
        Log.d("TAG", "onFragmentStopLazy() called with: " + "");
    }

    protected void onCreateViewLazy(Bundle savedInstanceState) {
        Log.d("TAG", "onCreateViewLazy() called with: " + "savedInstanceState = [" + savedInstanceState + "]");
    }

    protected void onResumeLazy() {
        Log.d("TAG", "onResumeLazy() called with: " + "");
    }

    protected void onPauseLazy() {
        Log.d("TAG", "onPauseLazy() called with: " + "");
    }

    protected void onDestroyViewLazy() {

    }



}

Basefragment的原始碼如下:

public class BaseFragment extends Fragment
{
    protected LayoutInflater inflater;
    private View contentView;
    private Context context;
    private ViewGroup container;
    @override 
    public void onCreate(Bundle savedInstanceState)
    {
       super.onCreate(savedInstanceState);
       context=getActivity().getApplicationContext();
    }
    //子類通過重寫onCreateView,呼叫setContentView進行佈局設定,否者contentView==null,返回Null
    @override
    public final View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState)
    {
       this.inflater=inflater;
       this.container=container;
       onCreateView(savedInstanceState);
       if(contentView==null)
          return super.onCreateView(inflater,container,savedInstanceState);
    return contentView;
    }
    protected void onCreateView(Bundle savedInstanceState)
    {

    }
    @override
    public void onDestroyView()
    {
       super.onDestroyView();
       contentView=null;
       container=null;
       inflater=null;
    }
    public Context getApplicationContex()
    {
       return context;
    }
    public void setContentView(int layoutResID)
    {
       setContetnView((ViewGroup)inflater.inflate(layoutResID,container,false));
    }
    public void setContentView(View view)
    {
       contentView=view;
    }
    public void getContentView()
    {
      return contentView;
    }
    public View findViewById(int id)
    {
       if(contentView!=null)
       {
          return contentView.findViewById(id);
       }
       return null;
    }
     // http://stackoverflow.com/questions/15207305/getting-the-error-java-lang-illegalstateexception-activity-has-been-destroyed
    @Override
    public void onDetach() {
        Log.d("TAG", "onDetach() : ");
        super.onDetach();
        try {
            Field childFragmentManager = Fragment.class.getDeclaredField("mChildFragmentManager");
            childFragmentManager.setAccessible(true);
            childFragmentManager.set(this, null);

        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void onDestroy() {
        Log.d("TAG", "onDestroy() : ");
        super.onDestroy();
    }

}

親測有效
備註:轉載地址 (http://www.jianshu.com/p/8a772b9df6d5)

相關文章