Fragment 的使用轻松上手

747 阅读26分钟
原文链接: blog.csdn.net

当我们导入Fragment的时候,一般有两个包可以选择,一个是android.app.Fragment,一个是 android.support.v4.app.Fragment。建议使用v4包中的Fragment,因为它可以在所有 android版本中保持一致。比如Fragment嵌套Fragment这个功能在 android4.2以后才开始支持,所以如果使用内置的FragmentAndroid 4.2之前的设备,会崩溃。


四.添加到Viewgroup



Fragment的生命周期


     

onAttach()。 当碎片和活动建立关联的时候调用

onCreateView()。  为碎片创建视图(加载布局)时调用

onActivityCreated()。  确保与碎片相关联的活动一定已经创建完毕的时候调用

onDestoryView()。  当与碎皮那关联的视图被移除的时候调用

onDetach()。  当碎片和活动解除关联的时候调用


添加FragmentActivity

有两种方法,一种是静态添加,直接将Fragment添加到Activity的布局中,一种是动态添加,添加到Activity的代码中。

新建MyFragment.javafragment_my.xml文件

MyFragment.java文件如下:

  1. public class MyFragment extends Fragment {  
  2.   
  3.     @Nullable  
  4.     @Override  
  5.     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {  
  6.         View view = inflater.inflate(R.layout.fragment_my, container, false);  
  7.         return view;  
  8.     }  
  9. }  
public class MyFragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_my, container, false);
        return view;
    }
}
fragment_my.xml文件

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.               android:layout_width="match_parent"  
  4.               android:layout_height="match_parent"  
  5.               android:background="#FF0000"  
  6.               android:gravity="center"  
  7.               android:orientation="vertical">  
  8.   
  9.     <TextView  
  10.         android:layout_width="wrap_content"  
  11.         android:layout_height="wrap_content"  
  12.         android:text="这是fragment"/>  
  13.   
  14. </LinearLayout>  
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:background="#FF0000"
              android:gravity="center"
              android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="这是fragment"/>

</LinearLayout>

1.静态添加

在Activity的布局中,添加如下标签:

  1. <fragment  
  2.     android:id="@+id/fragment_my"  
  3.     android:name="njj.fragment.MyFragment"  
  4.     class="njj.fragment.MyFragment1"  
  5.     android:layout_width="match_parent"  
  6.     android:layout_height="match_parent"/>  
    <fragment
        android:id="@+id/fragment_my"
        android:name="njj.fragment.MyFragment"
        class="njj.fragment.MyFragment1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
有两种方式,指定name属性,或者class属性,存在一个就可以,将fragment的完整类名写进去。如果class和name属性同时存在,将会以class属性为准。

2.动态添加

首先在Activity布局中,添加一个按钮,一个LinearLayout布局,布局主要是用来存放Fragment的容器,给布局指定id

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout  
  3.     xmlns:android="http://schemas.android.com/apk/res/android"  
  4.     xmlns:tools="http://schemas.android.com/tools"  
  5.     android:layout_width="match_parent"  
  6.     android:layout_height="match_parent"  
  7.     android:paddingBottom="@dimen/activity_vertical_margin"  
  8.     android:paddingLeft="@dimen/activity_horizontal_margin"  
  9.     android:paddingRight="@dimen/activity_horizontal_margin"  
  10.     android:paddingTop="@dimen/activity_vertical_margin"  
  11.     tools:context="njj.fragment.MainActivity">  
  12.   
  13.     <Button  
  14.         android:id="@+id/addBtn"  
  15.         android:layout_width="match_parent"  
  16.         android:layout_height="wrap_content"  
  17.         android:text="add Fragment"/>  
  18.   
  19.     <LinearLayout  
  20.         android:id="@+id/fragment_rl"  
  21.         android:layout_width="match_parent"  
  22.         android:layout_height="match_parent"  
  23.         android:layout_below="@+id/addBtn"  
  24.         android:orientation="vertical"/>  
  25. </RelativeLayout>  
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="njj.fragment.MainActivity">

    <Button
        android:id="@+id/addBtn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="add Fragment"/>

    <LinearLayout
        android:id="@+id/fragment_rl"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/addBtn"
        android:orientation="vertical"/>
</RelativeLayout>
然后,点击按钮,调用如下:

  1. mAddBtn.setOnClickListener(new View.OnClickListener() {  
  2.     @Override  
  3.     public void onClick(View view) {  
  4.         // 第一步:通过FragmentManager获得FragmentTransaction实例  
  5.         FragmentManager fragmentManager = getSupportFragmentManager();  
  6.         FragmentTransaction transaction = fragmentManager.beginTransaction();  
  7.   
  8.         // 第二步:调用add()方法,将Fragment对象添加到指定的布局id上。  
  9.         MyFragment myFragment = new MyFragment();  
  10.         transaction.add(R.id.fragment_rl, myFragment);  
  11.   
  12.         // 第三步:调用commit()方法,提交,生效  
  13.         transaction.commit();  
  14.     }  
  15. });  
        mAddBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // 第一步:通过FragmentManager获得FragmentTransaction实例
                FragmentManager fragmentManager = getSupportFragmentManager();
                FragmentTransaction transaction = fragmentManager.beginTransaction();

                // 第二步:调用add()方法,将Fragment对象添加到指定的布局id上。
                MyFragment myFragment = new MyFragment();
                transaction.add(R.id.fragment_rl, myFragment);

                // 第三步:调用commit()方法,提交,生效
                transaction.commit();
            }
        });

理解了几个类的含义和使用步骤后,完善的写法如下:

  1. FragmentManager fragmentManager = getSupportFragmentManager();  
  2. myFragment1 = (MyFragment1) fragmentManager.findFragmentById(R.id.fragment_rl2);  
  3.   
  4. if (myFragment1 == null) {  
  5.     myFragment1 = new MyFragment1();  
  6.     fragmentManager.beginTransaction().add(R.id.fragment_rl2, myFragment1).commit();  
  7. }  
                FragmentManager fragmentManager = getSupportFragmentManager();
                myFragment1 = (MyFragment1) fragmentManager.findFragmentById(R.id.fragment_rl2);

                if (myFragment1 == null) {
                    myFragment1 = new MyFragment1();
                    fragmentManager.beginTransaction().add(R.id.fragment_rl2, myFragment1).commit();
                }
1.为什么需要判null?

是因为当Activity因为配置发生改变(屏幕旋转)或者内存不足被系统杀死,造成重新创建时,我们的fragment会被保存下来,但是会创建新的FragmentManager,新的FragmentManager会首先去获取保存下来的fragment队列,重建fragment队列,从而回复之前的状态。

2.add(id,fragment)中的id有何用

一方面是告诉FragmentManager,此fragment应该放的位置,其次,以后可以通过findFragmentById(id)来查找。 


删除、替换、隐藏、显示

Fragment的添加、删除、替换、隐藏,显示,都是借助FragmentTransaction来完成的,所有对Fragment的改动,都需要调用commit()来提交。

  1. /** 
  2.  * 删除Fragment实例 
  3.  */  
  4. transaction.remove(myFragment);  
  5.   
  6. /** 
  7.  * 替换Fragment实例。执行更换的布局id,指定将要更换的Fragment实例 
  8.  */  
  9. transaction.replace(R.id.fragment_rl, myFragment)  
  10.   
  11. transaction.replace(R.id.fragment_rl1, myFragment1, "MF1");  
  12. // 当指明了fragment的tag时,可以通过findFragmentByTag来得到Fragment的实例  
  13. MyFragment1 fragment1 = (MyFragment1) fragmentManager.findFragmentByTag("MF1");  
  14.   
  15. /** 
  16.  * 隐藏Fragment实例 
  17.  */  
  18. transaction.hide(myFragment);  
  19.   
  20. /** 
  21.  * 显示Fragment实例 
  22.  */  
  23. transaction.show(myFragment);  
                /**
                 * 删除Fragment实例
                 */
                transaction.remove(myFragment);

                /**
                 * 替换Fragment实例。执行更换的布局id,指定将要更换的Fragment实例
                 */
                transaction.replace(R.id.fragment_rl, myFragment)
	
                transaction.replace(R.id.fragment_rl1, myFragment1, "MF1");
                // 当指明了fragment的tag时,可以通过findFragmentByTag来得到Fragment的实例
                MyFragment1 fragment1 = (MyFragment1) fragmentManager.findFragmentByTag("MF1");

                /**
                 * 隐藏Fragment实例
                 */
                transaction.hide(myFragment);

                /**
                 * 显示Fragment实例
                 */
                transaction.show(myFragment);


BackStack(回退栈)

调用addToBackStack()保存当前事务,当用户按下返回键,如果回退栈中保存之前的事务,便会执行事务回退,而不是执行activity的finish()。

  1. <span style="font-size:12px;">                transaction.addToBackStack( null);  
  2. </span>  
                transaction.addToBackStack(null);

在事务提交之前,调用addToBackStack()方法,就ok了。


获取FragmentManager的方法区别:

getFragmentManager(); // 3.0版本之前没有fragment的api所以要借用v4的getSupportFragmentManager()来使用。

getSupportFragmentManager(); // v4包的使用方式

getChildFragmentManager(); // 前面两个只使用Activity嵌套一级Fragment,如果Fragment里面嵌套二级甚至三级Fragment,就必须使用此方法。


Fragment通讯

1.Activity->Fragment

当我们需要通过Activity向Fragment传递数据时,可以使用Bundle和Arguments来实现,首先,在Activity中创建Fragment的时候,用Bundle绑定数据,

  1. public MyFragment getFragmentInstance() {  
  2.     Bundle bundle = new Bundle();  
  3.     bundle.putString("extra""info");  
  4.     if (myFragment == null) {  
  5.         myFragment = new MyFragment();  
  6.         myFragment.setArguments(bundle);  
  7.     }  
  8.     return myFragment;  
  9. }  
    public MyFragment getFragmentInstance() {
        Bundle bundle = new Bundle();
        bundle.putString("extra", "info");
        if (myFragment == null) {
            myFragment = new MyFragment();
            myFragment.setArguments(bundle);
        }
        return myFragment;
    }
然后在Fragment的onCreateView中将数据取出

  1. public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {  
  2.     Bundle bundle = getArguments();  
  3.     if (bundle != null) {  
  4.         Log.i("niejianjian"" -> extra -> " + bundle.getString( "extra"));  
  5.     }  
  6.     View view = inflater.inflate(R.layout.fragment_my, container, false);  
  7.     return view;  
  8. }  
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Bundle bundle = getArguments();
        if (bundle != null) {
            Log.i("niejianjian", " -> extra -> " + bundle.getString("extra"));
        }
        View view = inflater.inflate(R.layout.fragment_my, container, false);
        return view;
    }


2.Fragment->Activity

Fragment的操作想要传递到Activity,一般是使用回调的方式。

首先在Fragment中定义一个接口,用于在Activity回调:

  1. // 存放该Fragment的Activity必须实现此接口,否则报错。  
  2. public interface OnFragmentBtnClickListener {  
  3.     void showToast(String text);  
  4. }  
    // 存放该Fragment的Activity必须实现此接口,否则报错。
    public interface OnFragmentBtnClickListener {
        void showToast(String text);
    }
在Fragment中创建该接口,并且将实现我们接口的Activity,也就是存放该Fragment的Activity,强转为Listener,进行实例化。

  1. OnFragmentBtnClickListener listener;  
  2.   
  3. @Override  
  4. public void onAttach(Context context) {  
  5.     Log.i("niejianjian"" -> onAttach -> ");  
  6.     super.onAttach(context);  
  7.     try {  
  8.         listener = (OnFragmentBtnClickListener) getActivity();  
  9.     } catch (ClassCastException e) {  
  10.         Log.i("niejianjian"" -> activity must implement OnFragmentBtnClickListener -> ");  
  11.     }  
  12. }  
    OnFragmentBtnClickListener listener;

    @Override
    public void onAttach(Context context) {
        Log.i("niejianjian", " -> onAttach -> ");
        super.onAttach(context);
        try {
            listener = (OnFragmentBtnClickListener) getActivity();
        } catch (ClassCastException e) {
            Log.i("niejianjian", " -> activity must implement OnFragmentBtnClickListener -> ");
        }
    }
然后在需要执行操作的地方,调用接口的方法

  1. listener.showToast("Fragment Btn Click!!!");  
listener.showToast("Fragment Btn Click!!!");
最后在Activity中实现我们的接口,以及方法就OK了

  1. @Override  
  2. public void showToast(String text) {  
  3.     Log.i("niejianjian""Activity -> showToast -> " + text);  
  4. }  
    @Override
    public void showToast(String text) {
        Log.i("niejianjian", "Activity -> showToast -> " + text);
    }


3.Fragment  <->  Fragment

方法一:首先我们获得宿主Activity的FragmentManager,然后用findFragmentById来根据id获取到另外一Fragment对象,然后调用其方法

  1. MyFragment1 fragment1 = (MyFragment1) getActivity().getSupportFragmentManager().findFragmentById(R.id.fragment_rl2);  
  2. fragment1.setTextMethod();  
                MyFragment1 fragment1 = (MyFragment1) getActivity().getSupportFragmentManager().findFragmentById(R.id.fragment_rl2);
                fragment1.setTextMethod();
方法二:还是通过以宿主Activity为媒介,通过回调的方法,先将Fragment的信息传入到Activity,在从Activity调用另外一个Fragment的方法。

方法三,通过广播或者事件总线来实现。


Fragment常遇到的坑

1.getActivity()空指针

当系统内存不足时,回收了当前的的宿主Activity。如果我们在Fragment中执行异步操作,当执行完毕后,调用getActivity(),必然是会返回null。

解决方法就是在Fragment中定义一个全局变量Activity,然后使用mActivity代替getActivity(),这样就可以保证Fragment即使在onDetach后,还持有Activity的引用,不过这样会造成内存泄漏。

  1. protected Activity mActivity;  
  2. @Override  
  3. public void onAttach(Activity activity) {  
  4.     super.onAttach(activity);  
  5.     this.mActivity = activity;  
  6. }  
  7.   
  8. /** 
  9. *  如果你用了support 23的库,上面的方法会提示过时,有强迫症的小伙伴,可以用下面的方法代替 
  10. */  
  11. @Override  
  12. public void onAttach(Context context) {  
  13.     super.onAttach(context);  
  14.     this.mActivity = (Activity)context;  
protected Activity mActivity;
@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    this.mActivity = activity;
}

/**
*  如果你用了support 23的库,上面的方法会提示过时,有强迫症的小伙伴,可以用下面的方法代替
*/
@Override
public void onAttach(Context context) {
    super.onAttach(context);
    this.mActivity = (Activity)context;


ViewPager + Fragment使用

任意创建一个Fragment

  1. public class MyFragment0 extends Fragment {  
  2.   
  3.     @Nullable  
  4.     @Override  
  5.     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {  
  6.         View view = inflater.inflate(R.layout.fragment_my0, container, false);  
  7.         return view;  
  8.     }  
  9.   
  10. }  
public class MyFragment0 extends Fragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_my0, container, false);
        return view;
    }

}
然后将其多复制几个,用于添加到ViewPager上。

在Activity的布局中添加Viewpager控件

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout  
  3.     xmlns:android="http://schemas.android.com/apk/res/android"  
  4.     xmlns:tools="http://schemas.android.com/tools"  
  5.     android:layout_width="match_parent"  
  6.     android:layout_height="match_parent"  
  7.     tools:context="njj.fragment.MainActivity">  
  8.   
  9.     <android.support.v4.view.ViewPager  
  10.         android:id="@+id/viewpager"  
  11.         android:layout_width="match_parent"  
  12.         android:layout_height="match_parent"/>  
  13.   
  14. </RelativeLayout>  
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="njj.fragment.MainActivity">

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</RelativeLayout>
最后在Activity中实现,将Fragment添加到ViewPager中

  1. package njj.fragment;  
  2.   
  3. import android.os.Bundle;  
  4. import android.support.v4.app.Fragment;  
  5. import android.support.v4.app.FragmentManager;  
  6. import android.support.v4.app.FragmentPagerAdapter;  
  7. import android.support.v4.view.ViewPager;  
  8. import android.support.v7.app.AppCompatActivity;  
  9. import android.view.ViewGroup;  
  10. import android.view.Window;  
  11.   
  12. import java.util.ArrayList;  
  13. import java.util.List;  
  14.   
  15. public class MainActivity extends AppCompatActivity {  
  16.   
  17.     private ViewPager mViewPager;  
  18.     private List<Fragment> mFragmentList;  
  19.   
  20.     @Override  
  21.     protected void onCreate(Bundle savedInstanceState) {  
  22.         super.onCreate(savedInstanceState);  
  23.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  24.         setContentView(R.layout.activity_main);  
  25.   
  26.         mFragmentList = new ArrayList<>();  
  27.         mFragmentList.add(new MyFragment0());  
  28.         mFragmentList.add(new MyFragment1());  
  29.         mFragmentList.add(new MyFragment2());  
  30.         mFragmentList.add(new MyFragment3());  
  31.   
  32.         mViewPager = (ViewPager) findViewById(R.id.viewpager);  
  33.         mViewPager.setAdapter(new MyPagerAdapter(getSupportFragmentManager()));  
  34.         // 预加载的页面数,(前后)默认是1,最少也是1,设置0,也是1  
  35.         mViewPager.setOffscreenPageLimit(1);  
  36.   
  37.     }  
  38.     class MyPagerAdapter extends FragmentPagerAdapter {  
  39.   
  40.   
  41.         public MyPagerAdapter(FragmentManager fm) {  
  42.             super(fm);  
  43.         }  
  44.   
  45.         @Override  
  46.         public Fragment getItem(int position) {  
  47.             return mFragmentList.get(position);  
  48.         }  
  49.   
  50.         @Override  
  51.         public int getCount() {  
  52.             return mFragmentList.size();  
  53.         }  
  54.   
  55.         /** 
  56.          * 页面更新后调用此方法。可以用于处理tab视图的切换 
  57.          * http://blog.csdn.net/harvic880925/article/details/38487149 
  58.          */  
  59.         @Override  
  60.         public void finishUpdate(ViewGroup container) {  
  61.             super.finishUpdate(container);  
  62. //            Log.i("niejianjian"," ->  ->" + mViewPager.getCurrentItem());  
  63.         }  
  64.     }  
  65. }  
package njj.fragment;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.view.ViewGroup;
import android.view.Window;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private ViewPager mViewPager;
    private List<Fragment> mFragmentList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);

        mFragmentList = new ArrayList<>();
        mFragmentList.add(new MyFragment0());
        mFragmentList.add(new MyFragment1());
        mFragmentList.add(new MyFragment2());
        mFragmentList.add(new MyFragment3());

        mViewPager = (ViewPager) findViewById(R.id.viewpager);
        mViewPager.setAdapter(new MyPagerAdapter(getSupportFragmentManager()));
        // 预加载的页面数,(前后)默认是1,最少也是1,设置0,也是1
        mViewPager.setOffscreenPageLimit(1);

    }
    class MyPagerAdapter extends FragmentPagerAdapter {


        public MyPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            return mFragmentList.get(position);
        }

        @Override
        public int getCount() {
            return mFragmentList.size();
        }

        /**
         * 页面更新后调用此方法。可以用于处理tab视图的切换
         * http://blog.csdn.net/harvic880925/article/details/38487149
         */
        @Override
        public void finishUpdate(ViewGroup container) {
            super.finishUpdate(container);
//            Log.i("niejianjian"," ->  ->" + mViewPager.getCurrentItem());
        }
    }
}
此时,ViewPager + Fragment的简单实用就大功告成了。

ViewPager设置的Adapter有两种,分别是FragmentPagerAdapter和FragmentStatePagerAdapter,这两个的区别如下。

FragmentPagerAdapter:对于不再需要的Fragment,仅仅只会调用onDestoryView方法,也就是至销毁视图不销毁Fragment,所以不会执行onDetach方法。

FragmentStatePagerAdapter:会销毁不再需要的Fragment,一直调用到onDetach方法,将Activity和Fragment解绑。销毁时,会调用onSaveInstanceState(Bundle bundle)方法通过bundle将信息保存下来,当用户切换回来,可以通过bundle恢复生成新的fragment,也就是说,我们可以在onSaveInstanceState方法中保存一些数据,在onCreate中进行恢复创建。

不再需要的Fragment并不是不可见的Fragment,是否需要,要根据ViewPager当前显示哪个Fragment和Viewpager的setOffscreenPageLimit()方法设置的limit来共同决定的。

我们用声明周期来说明这些。我们将四个Fragment都实现声明周期方法:

  1. public class MyFragment0 extends Fragment {  
  2.   
  3.     @Nullable  
  4.     @Override  
  5.     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {  
  6.         Log.i("niejianjian","MyFragment0 -> onCreateView ->");  
  7.         View view = inflater.inflate(R.layout.fragment_my0, container, false);  
  8.   
  9.         return view;  
  10.     }  
  11.   
  12.     @Override  
  13.     public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {  
  14.         super.onViewCreated(view, savedInstanceState);  
  15.         Log.i("niejianjian","MyFragment0 -> onViewCreated ->");  
  16.     }  
  17.   
  18.     @Override  
  19.     public void onAttach(Context context) {  
  20.         super.onAttach(context);  
  21.         Log.i("niejianjian","MyFragment0 -> onAttach ->");  
  22.     }  
  23.   
  24.     @Override  
  25.     public void onCreate(@Nullable Bundle savedInstanceState) {  
  26.         super.onCreate(savedInstanceState);  
  27.         Log.i("niejianjian","MyFragment0 -> onCreate ->");  
  28.     }  
  29.   
  30.     @Override  
  31.     public void onActivityCreated(@Nullable Bundle savedInstanceState) {  
  32.         super.onActivityCreated(savedInstanceState);  
  33.         Log.i("niejianjian","MyFragment0 -> onActivityCreated ->");  
  34.     }  
  35.   
  36.     @Override  
  37.     public void onStart() {  
  38.         super.onStart();  
  39.         Log.i("niejianjian","MyFragment0 -> onStart ->");  
  40.     }  
  41.   
  42.     @Override  
  43.     public void onResume() {  
  44.         super.onResume();  
  45.         Log.i("niejianjian","MyFragment0 -> onResume ->");  
  46.     }  
  47.   
  48.     @Override  
  49.     public void onPause() {  
  50.         super.onPause();  
  51.         Log.i("niejianjian","MyFragment0 -> onPause ->");  
  52.     }  
  53.   
  54.     @Override  
  55.     public void onStop() {  
  56.         super.onStop();  
  57.         Log.i("niejianjian","MyFragment0 -> onStop ->");  
  58.     }  
  59.   
  60.     @Override  
  61.     public void onDestroyView() {  
  62.         super.onDestroyView();  
  63.         Log.i("niejianjian","MyFragment0 -> onDestroyView ->");  
  64.     }  
  65.   
  66.     @Override  
  67.     public void onDetach() {  
  68.         super.onDetach();  
  69.         Log.i("niejianjian","MyFragment0 -> onDetach ->");  
  70.     }  
  71. }  
public class MyFragment0 extends Fragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Log.i("niejianjian","MyFragment0 -> onCreateView ->");
        View view = inflater.inflate(R.layout.fragment_my0, container, false);

        return view;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        Log.i("niejianjian","MyFragment0 -> onViewCreated ->");
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        Log.i("niejianjian","MyFragment0 -> onAttach ->");
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i("niejianjian","MyFragment0 -> onCreate ->");
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Log.i("niejianjian","MyFragment0 -> onActivityCreated ->");
    }

    @Override
    public void onStart() {
        super.onStart();
        Log.i("niejianjian","MyFragment0 -> onStart ->");
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.i("niejianjian","MyFragment0 -> onResume ->");
    }

    @Override
    public void onPause() {
        super.onPause();
        Log.i("niejianjian","MyFragment0 -> onPause ->");
    }

    @Override
    public void onStop() {
        super.onStop();
        Log.i("niejianjian","MyFragment0 -> onStop ->");
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        Log.i("niejianjian","MyFragment0 -> onDestroyView ->");
    }

    @Override
    public void onDetach() {
        super.onDetach();
        Log.i("niejianjian","MyFragment0 -> onDetach ->");
    }
}

当我们设置setOffscreenPageLimit(1)的值为1的时候,当前页面的前后一个页面都是加载的。

启动应用,默认显示的是MyFragment0,生命周期显示如下:

  1. 12-29 10:38:46.130  25672-25672/njj.fragmeny I/niejianjian: MyFragment0 -> onAttach ->  
  2. 12-29 10:38:46.130  25672-25672/njj.fragmeny I/niejianjian: MyFragment0 -> onCreate ->  
  3. 12-29 10:38:46.130  25672-25672/njj.fragmeny I/niejianjian: MyFragment0 -> onCreateView ->  
  4. 12-29 10:38:46.130  25672-25672/njj.fragmeny I/niejianjian: MyFragment0 -> onViewCreated ->  
  5. 12-29 10:38:46.130  25672-25672/njj.fragmeny I/niejianjian: MyFragment0 -> onActivityCreated ->  
  6. 12-29 10:38:46.130  25672-25672/njj.fragmeny I/niejianjian: MyFragment0 -> onStart ->  
  7. 12-29 10:38:46.130  25672-25672/njj.fragmeny I/niejianjian: MyFragment0 -> onResume ->  
  8. 12-29 10:38:46.130  25672-25672/njj.fragmeny I/niejianjian: MyFragment1 -> onAttach ->  
  9. 12-29 10:38:46.130  25672-25672/njj.fragmeny I/niejianjian: MyFragment1 -> onCreate ->  
  10. 12-29 10:38:46.130  25672-25672/njj.fragmeny I/niejianjian: MyFragment1 -> onCreateView ->  
  11. 12-29 10:38:46.140  25672-25672/njj.fragmeny I/niejianjian: MyFragment1 -> onActivityCreated ->  
  12. 12-29 10:38:46.140  25672-25672/njj.fragmeny I/niejianjian: MyFragment1 -> onStart ->  
  13. 12-29 10:38:46.140  25672-25672/njj.fragmeny I/niejianjian: MyFragment1 -> onResume ->  
12-29 10:38:46.130 25672-25672/njj.fragmeny I/niejianjian: MyFragment0 -> onAttach ->
12-29 10:38:46.130 25672-25672/njj.fragmeny I/niejianjian: MyFragment0 -> onCreate ->
12-29 10:38:46.130 25672-25672/njj.fragmeny I/niejianjian: MyFragment0 -> onCreateView ->
12-29 10:38:46.130 25672-25672/njj.fragmeny I/niejianjian: MyFragment0 -> onViewCreated ->
12-29 10:38:46.130 25672-25672/njj.fragmeny I/niejianjian: MyFragment0 -> onActivityCreated ->
12-29 10:38:46.130 25672-25672/njj.fragmeny I/niejianjian: MyFragment0 -> onStart ->
12-29 10:38:46.130 25672-25672/njj.fragmeny I/niejianjian: MyFragment0 -> onResume ->
12-29 10:38:46.130 25672-25672/njj.fragmeny I/niejianjian: MyFragment1 -> onAttach ->
12-29 10:38:46.130 25672-25672/njj.fragmeny I/niejianjian: MyFragment1 -> onCreate ->
12-29 10:38:46.130 25672-25672/njj.fragmeny I/niejianjian: MyFragment1 -> onCreateView ->
12-29 10:38:46.140 25672-25672/njj.fragmeny I/niejianjian: MyFragment1 -> onActivityCreated ->
12-29 10:38:46.140 25672-25672/njj.fragmeny I/niejianjian: MyFragment1 -> onStart ->
12-29 10:38:46.140 25672-25672/njj.fragmeny I/niejianjian: MyFragment1 -> onResume ->
我们看到,此时MyFragment1也加载完了,然后我们滑动到第二个页面,也就是显示MyFragment1页面,

  1. 12-29 10:41:36.970  25672-25672/njj.fragmeny I/niejianjian: MyFragment2 -> onAttach ->  
  2. 12-29 10:41:36.970  25672-25672/njj.fragmeny I/niejianjian: MyFragment2 -> onCreate ->  
  3. 12-29 10:41:36.970  25672-25672/njj.fragmeny I/niejianjian: MyFragment2 -> onCreateView ->  
  4. 12-29 10:41:36.980  25672-25672/njj.fragmeny I/niejianjian: MyFragment2 -> onActivityCreated ->  
  5. 12-29 10:41:36.980  25672-25672/njj.fragmeny I/niejianjian: MyFragment2 -> onStart ->  
  6. 12-29 10:41:36.980  25672-25672/njj.fragmeny I/niejianjian: MyFragment2 -> onResume ->  
12-29 10:41:36.970 25672-25672/njj.fragmeny I/niejianjian: MyFragment2 -> onAttach ->
12-29 10:41:36.970 25672-25672/njj.fragmeny I/niejianjian: MyFragment2 -> onCreate ->
12-29 10:41:36.970 25672-25672/njj.fragmeny I/niejianjian: MyFragment2 -> onCreateView ->
12-29 10:41:36.980 25672-25672/njj.fragmeny I/niejianjian: MyFragment2 -> onActivityCreated ->
12-29 10:41:36.980 25672-25672/njj.fragmeny I/niejianjian: MyFragment2 -> onStart ->
12-29 10:41:36.980 25672-25672/njj.fragmeny I/niejianjian: MyFragment2 -> onResume ->
此时,第三个页面MyFragment2加载了。然后我们再滑动到第三个页面,也就是显示MyFragment2页面
  1. 12-29 10:42:42.470  25672-25672/njj.fragmeny I/niejianjian: MyFragment0 -> onPause ->  
  2. 12-29 10:42:42.470  25672-25672/njj.fragmeny I/niejianjian: MyFragment0 -> onStop ->  
  3. 12-29 10:42:42.470  25672-25672/njj.fragmeny I/niejianjian: MyFragment0 -> onDestroyView ->  
  4. 12-29 10:42:42.470  25672-25672/njj.fragmeny I/niejianjian: MyFragment3 -> onAttach ->  
  5. 12-29 10:42:42.470  25672-25672/njj.fragmeny I/niejianjian: MyFragment3 -> onCreate ->  
  6. 12-29 10:42:42.470  25672-25672/njj.fragmeny I/niejianjian: MyFragment3 -> onCreateView ->  
  7. 12-29 10:42:42.480  25672-25672/njj.fragmeny I/niejianjian: MyFragment3 -> onActivityCreated ->  
  8. 12-29 10:42:42.480  25672-25672/njj.fragmeny I/niejianjian: MyFragment3 -> onStart ->  
  9. 12-29 10:42:42.480  25672-25672/njj.fragmeny I/niejianjian: MyFragment3 -> onResume ->  
12-29 10:42:42.470 25672-25672/njj.fragmeny I/niejianjian: MyFragment0 -> onPause ->
12-29 10:42:42.470 25672-25672/njj.fragmeny I/niejianjian: MyFragment0 -> onStop ->
12-29 10:42:42.470 25672-25672/njj.fragmeny I/niejianjian: MyFragment0 -> onDestroyView ->
12-29 10:42:42.470 25672-25672/njj.fragmeny I/niejianjian: MyFragment3 -> onAttach ->
12-29 10:42:42.470 25672-25672/njj.fragmeny I/niejianjian: MyFragment3 -> onCreate ->
12-29 10:42:42.470 25672-25672/njj.fragmeny I/niejianjian: MyFragment3 -> onCreateView ->
12-29 10:42:42.480 25672-25672/njj.fragmeny I/niejianjian: MyFragment3 -> onActivityCreated ->
12-29 10:42:42.480 25672-25672/njj.fragmeny I/niejianjian: MyFragment3 -> onStart ->
12-29 10:42:42.480 25672-25672/njj.fragmeny I/niejianjian: MyFragment3 -> onResume ->
然后我们发现MyFragment3加载完的同时,MyFragment0销毁了。

因为我们设置的setOffscreenPageLimit为1,也就是当前页面的前后1个页面是需要的,不需要的,会执行销毁视图。当我们滑动到第三个页面也就是MyFragment2显示的时候,它的前面是MyFragment1,后面是MyFragment3,此时,MyFragment0是不需要的,所以,它会销毁视图,当我们在滑动回第二个页面(MyFragment1显示)

  1. 12-29 10:45:46.970  25672-25672/njj.fragmeny I/niejianjian: MyFragment0 -> onCreateView ->  
  2. 12-29 10:45:46.970  25672-25672/njj.fragmeny I/niejianjian: MyFragment0 -> onViewCreated ->  
  3. 12-29 10:45:46.970  25672-25672/njj.fragmeny I/niejianjian: MyFragment0 -> onActivityCreated ->  
  4. 12-29 10:45:46.970  25672-25672/njj.fragmeny I/niejianjian: MyFragment3 -> onPause ->  
  5. 12-29 10:45:46.970  25672-25672/njj.fragmeny I/niejianjian: MyFragment3 -> onStop ->  
  6. 12-29 10:45:46.970  25672-25672/njj.fragmeny I/niejianjian: MyFragment3 -> onDestroyView ->  
  7. 12-29 10:45:46.970  25672-25672/njj.fragmeny I/niejianjian: MyFragment0 -> onStart ->  
  8. 12-29 10:45:46.970  25672-25672/njj.fragmeny I/niejianjian: MyFragment0 -> onResume ->  
12-29 10:45:46.970 25672-25672/njj.fragmeny I/niejianjian: MyFragment0 -> onCreateView ->
12-29 10:45:46.970 25672-25672/njj.fragmeny I/niejianjian: MyFragment0 -> onViewCreated ->
12-29 10:45:46.970 25672-25672/njj.fragmeny I/niejianjian: MyFragment0 -> onActivityCreated ->
12-29 10:45:46.970 25672-25672/njj.fragmeny I/niejianjian: MyFragment3 -> onPause ->
12-29 10:45:46.970 25672-25672/njj.fragmeny I/niejianjian: MyFragment3 -> onStop ->
12-29 10:45:46.970 25672-25672/njj.fragmeny I/niejianjian: MyFragment3 -> onDestroyView ->
12-29 10:45:46.970 25672-25672/njj.fragmeny I/niejianjian: MyFragment0 -> onStart ->
12-29 10:45:46.970 25672-25672/njj.fragmeny I/niejianjian: MyFragment0 -> onResume ->
此时,又会重新绑定试图。

我们设置FragmentPageAdapter和FragmentStatePageAdapter的区别就是在于,会多执行onAttach和onDetach。使用哪个,根据自己的需求。

懒加载对setuserVisibleHint()进行处理

  1. @Override  
  2. public void setUserVisibleHint(boolean isVisibleToUser) {  
  3.     super.setUserVisibleHint(isVisibleToUser);  
  4.     if (getUserVisibleHint()){  
  5.           
  6.     }  
  7.     Log.i("niejianjian","MyFragment0 -> isVisibleToUser -> " + isVisibleToUser);  
  8. }  
    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (getUserVisibleHint()){
            
        }
        Log.i("niejianjian","MyFragment0 -> isVisibleToUser -> " + isVisibleToUser);
    }

blog.csdn.net/linglongxin…




参考连接:

juejin.cn/post/684490…

yifeng.studio/2016/12/15/…

http://www.jianshu.com/p/662c46cd3b5f