总结

参考:https://www.jianshu.com/p/28ca4cbe190c

参考:https://www.jianshu.com/p/11c8ced79193

1.生命周期

参考:https://blog.csdn.net/gyh790005156/article/details/79487576

2.Fragment实现原理和Back Stack

参考:https://www.jianshu.com/p/28ca4cbe190c

参考:https://www.jianshu.com/p/11c8ced79193

面试题

1. Fragment为什么被称为第五大组件

Fragment比Activity更节省内存,其切换模式也更加舒适,使用频率不低于四大组件,且有自己的生命周期,并且必须依付于Activity

2. Activity创建Fragment的方式

  • 静态创建具体步骤

首先我们同样需要注册一个xml文件,然后创建与之对应的java文件,通过onCreatView()的返回方法进行关联,最后我们需要在Activity中进行配置相关参数即在Activity的xml文件中放上fragment的位置。

  • 动态创建具体步骤

(1)创建待添加的碎片实例

(2)获取FragmentManager,在活动中可以直接通过调用 getSupportFragmentManager()方法得到。

(3)开启一个事务,通过调用beginTransaction()方法开启。

(4)向容器内添加或替换碎片,一般使用repalce()方法实现,需要传入容器的id和待添加的碎片实例。

(5)提交事务,调用commit()方法来完成。

3. FragmentPageAdapter和FragmentPageStateAdapter的区别

  • FragmentPagerAdapter:

适用于页面较少的情况,后者适用于页面较多的情况,通过源码了解,主要查看destroyItem方法中的最后一行,mcurtransaction.remove(fragment),通过这行代码了解到,FragmentStatePagerAdapter是真正释放fragment内存,

  • FragmentStatePagerAdapter

在FragmentPagerAdapter的destroyItem方法中所调用的是mcurtransaction.detach(fragment),他仅仅是将fragment的页面与activity的页面抽离开来,并没有真正的销毁fragment释放内存.

4. Fragment的生命周期

android fragment 面试_第1张图片

5. Fragment通信

  • Fragment与Activity通信方式

1.在fragment中调用activity中的方法getActivity

2.在Activity中条用Fragment中的方法,一般常用的是接口回调,在fragment中创建接口,在activity中实现接口,这样就能完成activity中调用fragment中的方法

3.在Fragment中调用Fragment中的方法,首先先通过getactivity方法,获取activity的方法,然后通过fingFragmentById获取到另外一个fragment的方法,然后进行调用

6. ViewPager与Fragment结合使用时的懒加载问题

  • 所谓的 “懒加载” 就是数据只有在Fragment对于用户可见的时才进行加载。因为ViewPager会帮我们预先初始化Fragment。由于这个特性,我们不能把数据的加载放到onCreateView方法或者onCreate方法中。

因此,我们需要判定Fragment在什么时候是处于可见的状态。一般我们通常是通过Fragment中的生命周期方法onResume来判断Fragment是否可见,但是由于ViewPager预加载的特性,Fragment即便不可见也会执行onResume方法,因此使用这个方法进行可见性的判断就行不通了。这个时候我们需要用到下面的这个方法来进行Fragment可见性的判断:

setUserVisibleHint()方法:

什么时候被调用?

  • 当fragment被创建的时,setUserVisibleHint(boolean isVisibleToUser)方法会被调用,且传入参数值为false。
  • 当fragment可见时,setUserVisibleHint(boolean isVisibleToUser)方法会被调用,且传入参数值为true。
  • 当fragment由 可见 -> 不可见 时,setUserVisibleHint(boolean isVisibleToUser)方法会被调用,且传入参数值为false。

只需要当setUserVisibleHint(boolean isVisibleToUser)方法中的 isVisibleToUser 参数的值为true的时候我们才开始进行数据的加载

注意事项:
setUserVisibleHint(boolean isVisibleToUser)方法在Fragment的生命周期方法onCreate 之前调用的,也就是说他并不在Fragment的生命周期中。既然是在 onCreate 方法之前被调用,这样就存在许多不确定因素,如果Fragmnet的View还没有完成初始化之前,就在setUserVisibleHint()方法中进行UI的操作,这样显然会导致空指针的出现

解决方法:

我们需要对Fragment创建的View进行缓存,确保缓存的View不为空的情况下我们才可以在setUserVisibleHint方法中进行UI操作。

/** * Fragment的基类(懒加载) * Created by wangke on 17-8-15. */public abstract class BaseLazyFragment extends RxFragment {    private String TAG;    //标记当前Fragment的可见状态    private boolean isFragmentVisible;    private boolean isFirstVisible;    //对Fragment中加载的View进行缓存    private View mRootView;    private Unbinder mUnbinder;    public BaseLazyFragment(String TAG) {        this.TAG = TAG;    }    /**     * 当Fragment添加到Activity的时候最先调用此方法     *     * @param context 上下文对象     */    @Override    public void onAttach(Context context) {        super.onAttach(context);        //获取Fragment之间传递过来的参数        initArgs(getArguments());    }    /**     * 获取Fragment中传递过来的参数,选择重写     *     * @param arguments     */    protected void initArgs(Bundle arguments) {    }    @Override    public void onCreate(@Nullable Bundle savedInstanceState) {        LogHelper.i("wwk", TAG + " ===>onCreate");        super.onCreate(savedInstanceState);        initVariable();    }    @Nullable    @Override    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {        View view = inflater.inflate(getContentLayoutId(), container, false);        mUnbinder = ButterKnife.bind(this, view);        initWidget(mRootView);        initEvent();        return view;    }    @Override    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {        LogHelper.i("wwk", TAG + " ===>onViewCreated");        if (mRootView == null) {            mRootView = view;            if (getUserVisibleHint()) {                if (isFirstVisible) {                    //处于可见状态并且Fragment是第一次开启                    onFragmentFirstVisible();                    isFirstVisible = false;                }                onFragmentVisibleChange(true);                isFragmentVisible = true;            }        }        //直接使用缓存的mRootView        super.onViewCreated(mRootView, savedInstanceState);    }    /**     * 初始化控件事件,选择重写     */    private void initEvent() {    }    /**     * 初始化组件     *     * @param view     */    protected abstract void initWidget(View view);    /**     * 当Fragment第一次创建的时候调用,如果不可见则isVisible的参数值为false     * 当Fragment对于用户可见时调用,此时的isVisibleToUser参数值为true     * 当Fragment当前的状态由可见变为不可见时调用,此时的isVisibleToUser参数为false     *     * @param isVisibleToUser true : 可见     *                        false : 不可见     */    @Override    public void setUserVisibleHint(boolean isVisibleToUser) {        LogHelper.i("tag", TAG + " ==> setUserVisibleHint ");        super.setUserVisibleHint(isVisibleToUser);        //setUserVisibleHint()的调用在Fragment的声明周期外调用,需要保证rootView不为空的时候调用 onFragmentVisibleChange方法        if (mRootView == null) {            return;        }        //第一次被开启,并且对用户可见(这个if语句中的判断一般不会被执行到,setUserVisibleHint方法的调用时mRootView还没有被缓存)        if (isFirstVisible && isVisibleToUser) {            //当Fragment第一次可见的时候调用            onFragmentFirstVisible();            isFirstVisible = false;        }        //Fragment对于用户可见(已经不是第一次开启)        if (isVisibleToUser) {            onFragmentVisibleChange(true);            isFragmentVisible = true;            return;        }        //能执行到这里表明 Fragment对于用户已经处于不可见的状态        if (isFragmentVisible) {            //由 可见 -> 不可见            isFragmentVisible = false;            onFragmentVisibleChange(false);        }    }    /**     * 获取填充Fragment的View的id     *     * @return     */    protected abstract int getContentLayoutId();    /**     * 当Fragment的状态发生变化的时候调用,用于进行数据的刷新     *     * @param isVisible true  不可见 -> 可见     *                  false 可见  -> 不可见     */    protected abstract void onFragmentVisibleChange(boolean isVisible);    /**     * 当Fragment第一次被开启的时候调用,用于请求数据     */    protected abstract void onFragmentFirstVisible();    /**     * 获取当前Fragment的可见状态     *     * @return     */    protected boolean isFragmentVisible() {        return isFragmentVisible;    }    /**     * 给变量赋初始值     */    private void initVariable() {        //标记是否是第一次开启当前Fragment        isFirstVisible = true;        //标记Fragment对于用户是否可见        isFragmentVisible = false;        //缓存Fragment创建出来的View        mRootView = null;    }    @Override    public void onDestroy() {        initVariable();        mUnbinder.unbind();        super.onDestroy();    }}

更多相关文章

  1. android中在切换fragment时,怎样做到无需重复加载数据的方法。
  2. android 动态改变控件大小的方法
  3. android发送彩信的两种方法
  4. Android 学习笔记3(Activity之间参数传递)
  5. android--------根据文件路径加载指定文件
  6. Android中自定义ProgressDialog实现加载滚动条(加载中…)效果
  7. Android:禁止滚动的解决方法
  8. Android AlertDialog包含EditText,软键盘不能弹出的解决方法
  9. Android 将一个数据对象保存到本地以及读取的方法

随机推荐

  1. Android(安卓)Json数据解析
  2. android ContentProvider 使用实例
  3. How property system works on Android
  4. Android推送 基于MQTT
  5. Java/Android汉字转拼音
  6. Android(安卓)OkHeaderInterceptor
  7. android中 spannable的使用【转】
  8. android sdk manager’s error’s solves
  9. android view 上下左右滑动 事件
  10. Android之截屏代码