Fragment相关面试题

1、在fragment中为什么有时getActivity()会为null?

Fragment 的 getActivity() 会在 onDetach 之后释放持有的 Activity,因而返回了 null。

2、Fragment为什么有的时候会重叠,怎么产生的,又如何解决?

一般满足下面2个条件才可能会发生重叠:

  1. 发生了页面重启(旋转屏幕、内存不足等情况被强杀重启);

系统在页面重启前,帮我们保存了Fragment的状态,但是在重启后恢复时,视图的可见状态没帮我们保存,而Fragment默认的是show状态,所以产生了Fragment重叠现象。

  1. 重复replace|add Fragment 或者 使用show , hide控制Fragment。

我们会在Activity的onCreate()里或者Fragment的onCreateView()里加载根Fragment,如果在这里没有进行页面重启的判断的话,就可能导致重复加载Fragment引起重叠;

在使用replace加载Fragment时,页面重启后,Fragment视图都还没创建,所以mHidden没有意义,不会发生重叠现象;而在使用add加载时,视图是存在的并且叠加在一起,页面重启后 mHidden=false,所有的Fragment都会是show状态显示出来(即VISIBLE),从而造成了Fragment重叠!

3、Fragment懒加载

为什么要懒加载

如果我们没有对 Fragment 进行懒加载处理,那么我们就会无缘无故的加载一些并不可见的 Fragment , 也就会造成用户流量的无故消耗(我们会在 Fragment 相关生命周期函数中,请求网络或其他数据操作)。

这里"不可见的Fragment"是指,实际不可见但是相关可见生命周期函数(如 onResume 方法)被调用的 Fragment

如何实现懒加载

1、add+show+hide 模式下的方案

在没有添加懒加载之前,只要使用 add+show+hide 的方式控制并显示 Fragment, 那么不管 Fragment 是否嵌套,在初始化后,如果只调用了add+show,同级下的 Fragment 的相关生命周期函数都会被调用。且调用的生命周期函数如下所示:

onAttach -> onCreate -> onCreatedView -> onActivityCreated -> onStart -> onResume

Fragment 完整生命周期:onAttach -> onCreate -> onCreatedView -> onActivityCreated -> onStart -> onResume -> onPause -> onStop -> onDestroyView -> onDestroy -> onDetach

我们要在 add+show+hide 模式下控制 Fragment 的懒加载,我们只需要做这两步:

  • 我们需要在 onResume() 函数中调用 isHidden() 函数,来处理默认显示的 Fragment;
  • 在 onHiddenChanged 函数中控制其他不可见的Fragment。
abstract class LazyFragment:Fragment(){

    private var isLoaded = false //控制是否执行懒加载
	/**
     * 当前Fragment是否对用户可见
     */
    private var isVisibleToUser = false

    override fun onResume() {
        super.onResume()
        judgeLazyInit()

    }
    override fun onHiddenChanged(hidden: Boolean) {
        super.onHiddenChanged(hidden)
        isVisibleToUser = !hidden
        judgeLazyInit()
    }

    private fun judgeLazyInit() {
        if (!isLoaded && !isHidden) {
            lazyInit()
            isLoaded = true
        }
    }

     override fun onDestroyView() {
        super.onDestroyView()
        isLoaded = false
    }

    //懒加载方法
    abstract fun lazyInit()
}

2、ViewPager+Fragment 模式下的方案

我们需要控制 setUserVisibleHint(boolean isVisibleToUser) 函数,该函数的声明如下所示:

    public void setUserVisibleHint(boolean isVisibleToUser) {}

该函数与 onHiddenChanged() 作用非常相似,都是通过传入的参数值来判断当前 Fragment 是否对用户可见,只是 onHiddenChanged() 是在 add+show+hide 模式下使用,而 setUserVisibleHint 是在 ViewPager+Fragment 模式下使用。

如果我们想对 ViewPager 中的 Fragment 懒加载,我们需要这样处理:

abstract class LazyFragment : Fragment() {

    /**
     * 是否执行懒加载
     */
    private var isLoaded = false

    /**
     * 当前Fragment是否对用户可见
     */
    private var isVisibleToUser = false

    /**
     * 当使用ViewPager+Fragment形式会调用该方法时,setUserVisibleHint会优先Fragment生命周期函数调用,
     * 所以这个时候就,会导致在setUserVisibleHint方法执行时就执行了懒加载,
     * 而不是在onResume方法实际调用的时候执行懒加载。所以需要这个变量
     */
    private var isCallResume = false

    override fun onResume() {
        super.onResume()
        isCallResume = true
        judgeLazyInit()
    }


    private fun judgeLazyInit() {
        if (!isLoaded && isVisibleToUser && isCallResume) {
            lazyInit()
            Log.d(TAG, "lazyInit:!!!!!!!)
            isLoaded = true
        }
    }

    override fun onHiddenChanged(hidden: Boolean) {
        super.onHiddenChanged(hidden)
        isVisibleToUser = !hidden
        judgeLazyInit()
    }

    //在Fragment销毁View的时候,重置状态
    override fun onDestroyView() {
        super.onDestroyView()
        isLoaded = false
        isVisibleToUser = false
        isCallResume = false
    }

    override fun setUserVisibleHint(isVisibleToUser: Boolean) {
        super.setUserVisibleHint(isVisibleToUser)
        this.isVisibleToUser = isVisibleToUser
        judgeLazyInit()
    }

    abstract fun lazyInit()
}

4、Fragment的replace和add的区别?

Fragment 的容器一个 FrameLayout,add 的时候是把所有的 Fragment 一层一层的叠加到了 FrameLayout 上了,而 replace 的话首先将该容器中的其他 Fragment 去除掉然后将当前 Fragment 添加到容器中。

一个 Fragment 容器中只能添加一个 Fragment 种类,如果多次添加则会报异常,导致程序终止,而 replace 则无所谓,随便切换。

因为通过 add 的方法添加的 Fragment,每个 Fragment 只能添加一次,因此如果要想达到切换效果需要通过Fragment 的的 hide 和 show 方法结合者使用。将要显示的 show 出来,将其他 hide 起来。这个过程 Fragment 的生命周期没有变化。

通 过 replace 切 换 Fragment , 每 次 都 会 执 行 上 一 个 Fragment 的 onDestroyView , 新 Fragment 的onCreateView、onStart、onResume 方法。

5、getFragmentManager,getSupportFragmentManager,getChildFragmentManager三者之间的区别

因为fragment是3.0之后才有的api,就可以直接用getFragmentManager()这个方法来获取fragment管理器对象。但是3.0之前的版本如果也想获得fragment管理器对象怎么办呢?因此出现了getSupportFragmentManager,用于支持3.0以下的安卓系统API版本。

而getChildFragmentManager 是针对fragment嵌套fragment。

getFragmentManager()所得到的是所在fragment 的父容器的管理器(此处重点在父容器),

getChildFragmentManager()所得到的是在fragment 里面子容器的管理器(此处重点在子容器)。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值