Fragment面试题目整理

Fragment面试题目整理

为什么引入Fragment?

Android在api11中加入了Fragment,主要是给大屏设备上进行动态灵活的UI设计提供支持,更多的情况下我们把Fragment作为一个可重复利用的模块化组件,利用它自身的生命周期来对功能模块进行分离。

image

Fragment加载到Activity的两种方式:

  1. 静态加载,直接添加Fragment到Activity的布局文件房中。

  2. 动态的在Activity中添加Fragment

FragmentPagerAdapter与FragmentStatePagerAdapter的区别?

FragmentPagerAdapter一般用于少量界面的ViewPager,划过的Fragment会一直保存在内存中不会被销毁。而FragmentStatePagerAdapter适用于界面较多的ViewPager,它会保存当前的界面以及下一个界面和上一个界面,最多保存三个,其他的会在destroyItem()方法中被销毁调,可以节省内存占用。

Fragmnet的生命周期

image

Fragment通信

  1. 在Fragment中调用Activity中的方法

    通过getActivity()方法获取所附属的Activity后调用当中的方法

  2. 在Activity中调用Fragment中的方法

    采用接口回调的形式

  3. 在Fragment中调用Fragment中的方法

    findFragmentById()

Fragment的replace、add、remove方法

  • add 是把一个Fragment添加到一个容器当中。一般在使用add的时候会配合 hide,show一起使用,为了避免Fragment的重复创建节省资源。

  • replace 在添加Fragment到容器之前先移除掉相同id的所有Fragment然后再进行添加

无法在activity调用了onSaveInstanceState之后再执行commit进行添加Fragment

Activity被系统回收(界面已经不存在了),为了能在下次打开的时候恢复原来的样子,系统为我们保存界面的所有状态,这个时候再去修改界面理论上肯定是不被允许的,为了避免这种异常可以使用:

transaction.commitAllowingStateLoss();

来提交添加Fragment到Activity的事务,与commit()不同的是使用这种方法允许丢失界面的状态和信息。

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操作。

BaseLazyFragment.java


/**
 * 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();
    }


}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
面试中,可能会涉及到关于Fragment的一些常见问题,以下是一些可能会被问到的问题及其答案: 1. 什么是FragmentFragmentAndroid中的一种可重用的组件,它可以与Activity进行交互,作为Activity界面的一部分进行展示。它可以有自己的布局和生命周期,并且可以被添加、移除、替换或者在Activity中进行切换。 2. Fragment的生命周期是什么样的? Fragment的生命周期包括以下几个方法:onAttach、onCreate、onCreateView、onActivityCreated、onStart、onResume、onPause、onStop、onDestroyView、onDestroy和onDetach。这些方法提供了在Fragment生命周期中不同阶段执行代码的机会,开发者可以在这些方法中处理相关的逻辑。 3. Fragment和Activity之间的通信方式有哪些? Fragment和Activity之间可以通过接口回调、广播、观察者模式等方式进行通信。其中,接口回调是最常见的方式,Activity可以实现一个接口,Fragment通过该接口将数据传递给Activity。广播和观察者模式可以用于更复杂的场景,可以实现多个Fragment和Activity之间的通信。 4. FragmentPagerAdapter和FragmentStatePagerAdapter有什么区别? FragmentPagerAdapter和FragmentStatePagerAdapter都是ViewPager的适配器,用于管理Fragment的切换。区别在于FragmentPagerAdapter会保留Fragment的状态,而FragmentStatePagerAdapter会销毁之前的Fragment,适用于有大量Fragment的情况。 5. getFragmentManager、getSupportFragmentManager和getChildFragmentManager有什么区别? getFragmentManager是用于获取与当前Fragment关联的FragmentManager,通常用于在Fragment中获取父级Activity的FragmentManager。getSupportFragmentManager是Support库中的方法,用于获取兼容版本的FragmentManager,通常用于在Support库中使用Fragment。getChildFragmentManager是用于获取Fragment中嵌套的子级FragmentManager,通常用于在一个Fragment中管理另一个Fragment。 以上是一些关于Fragment的常见面试题及其答案。希望对你有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值