lifecycle安卓(Android开发 :Fragment懒加载的几种方式与性能对比)
本文目录
- Android开发 :Fragment懒加载的几种方式与性能对比
- Android-Lifecycle原理解析
- Android Lifecycle源码解析
- LottieAndroid使用详解及源码解析—轻而易举实现各种复杂动画
- 安卓开发:如何得知当前activity是被压入后台,还是跳转到新的activity
Android开发 :Fragment懒加载的几种方式与性能对比
TabLayout+ViewPager+Fragment是我们开发常用的组合。ViewPager的默认机制就是把全部的Fragment都加载出来,而为了保障一些用户体验,我们使用懒加载的Fragment,就是让我们再用户可见这个Fragment之后才处理业务逻辑。
而我们在一些设备或版本中可能就出现懒加载失效的问题。其实谷歌早就把一些懒加载的方案都标记弃用了,我们一直都用的老的随时会失效的Api。万一哪天彻底失效了就会导致线上事故。
接下来我们就看看Fragment的懒加载是如何演变的。谷歌又是推荐我们如何使用的。
在AndroidX还没出来的时候,大家的懒加载应该都是这样。判断setUserVisibleHint的方法,当用户可见的时候才回调方法去加载逻辑。
例如的我封装:
使用的示例:
扩展方法:
Fragment:
到此就实现了onLazyInitData的回调,只有出现Fragment显示在前台的时候才会调用方法,执行逻辑。
每次判断 setUserVisibleHint 和 onHiddenChanged 也麻烦,并且他们并不稳定,我也遇到过不回调的时候。
Android出来之后,给 FragmentStatePagerAdapter 添加了一个 @Behavior int behavior 的参数。
其本质就是内部帮你处理和切换MaxLifecycle:
如何使用呢:
之前的扩展方法以及预留了 behavior 参数,当为1的时候就不会回调 setUserVisibleHint 方法了,我们直接监听 OnResume 即可。
注意这个页面继承的就不是我们自定义的懒加载Fragment了。普通的Fragment 回调 onResume 即可。
ViewPager2出来之后。我们的 FragmentStatePagerAdapter 退出历史舞台。
即便能用,即便效果还是和ViewPage2的效果一样,但是还是标记废弃了。具体原因我也不知道,据说是因为老版本会出现问题导致数据丢失,页面空白。
ViewPage2我们都知道内部是通过RV实现的。但是对于Fragment的处理有单独的Adapter实现。
扩展方法:
使用:
使用的方式和ViewPager差不多,这里的Fragment也是使用普通的Fragment即可。
内存占用分别取三组数据
ViewPager数据
ViewPager2数据
结论 ViewPager2基于RV实现的效果还是比老版ViewPager要骚好一点。
并且老版本标记废弃,大家如果是用ViewPager2的话,还是推荐使用ViewPager2实现。如果大家还是用的老版本的ViewPager也推荐使用behavor参数。使用 onResume 实现懒加载的实现。以后再换到ViewPager2的话,可以无缝切换过来。
说明一下,测试数据仅供参考,毕竟我也不是专业测试,测试数据源也不不多。如有不对的地方,也望大家指正。
Android-Lifecycle原理解析
Event触发的时机:
而在androidx.activity.ComponentActivity和androidx.core.app.ComponentActivity中,该方法的实现,其实都是一样的。
但是这两个Activity,其实都有自己的mLifecycleRegistry对象。
LifecycleRegistry对象其实可以理解为观察者模式中的Observable,也就是被观察者,而LifecycleRegistry对象的创建,其实是传入一个LifecycleOwner实现类对象,而androidx.activity.ComponentActivity和androidx.core.app.ComponentActivity实现了LifecycleOwner接口,所以传入的是this。
LifecycleRegistry中聚合了多个LifecycleObserver,生命周期改变时,通知LifecycleObserver进行相应方法的调用。 在LifecycleRegistry类中的addObserver方法中,其实就是通过封装LifecycleObserver生成了一个ObserverWithState对象,然后放入FastSafeIterableMap中,而FastSafeIterableMap其实就是一个自定义列表,用于保存观察者并且可在遍历期间处理删除/添加。 其实在自定义的某个类去实现LifecycleObserver接口的时候,在activity中,是需要通过getLifecycle().addObserver()进行注册的,这个过程其实就是调用了LifecycleRegistry的addObserver()方法。
ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);会将LifecycleObserver对象封装在ReflectiveGenericLifecycleObserver对象中。但是这里的需要判断是实现了哪个接口,比如androidx.activity.ComponentActivity中的构造函数中,因为是直接new LifecycleEventObserver匿名内部类实现接口对象,则isLifecycleEventObserver为true,就不会new ReflectiveGenericLifecycleObserver(),而在自定义一个类的时候,一般实现LifecycleObserver接口,则就会new ReflectiveGenericLifecycleObserver()
androidx.activity.ComponentActivity的构造函数:这里是new LifecycleEventObserver
自定义的BasePresenter:这里是实现LifecycleObserver接口
所以上面的两种不同的实现,BasePresenter实现的是LifecycleObserver,所以这个LifecycleObserver的最终实现是ReflectiveGenericLifecycleObserver。而ComponentActivity因为是new LifecycleEventObserver,所以这个匿名内部类对象就是最终实现。
在androidx.core.app.ComponentActivity的onCreate方法中,会调用
这里使用ReportFragment,如果是api29以及以上的,则可以直接注册回调来获取Activity的生命周期回调。如果是api29以下的,则需要手动给Activity添加一个空白的Fragment,类似于Glide监听生命周期回调的做法。
LifecycleCallbacks的定义如上,是在ReportFragment中定义的,其实就是使用了Application.ActivityLifecycleCallbacks来实现了。 其实就是在androidx.core.app.ComponentActivity中添加一个ReportFragment,而ReportFragment的生命周期方法,其实都调用了一个dispatch方法。
所以在ReportFragment的生命周期方法,其实就会通过调用对应的dispatch方法进而调用到了Activity的getLifecycle()方法获取到一个LifecycleRegistry对象,然后调用LifecycleRegistry的handleLifecycleEvent()方法。
这里需要事先获取到Activity的下一个生命周期状态,而这个状态过程其实与Fragment的类似,都是先升序,然后再降序的一个过程。即ON_CREATE是CREATED,ON_RESUME是RESUMED,然后ON_PAUSE是变成STARTED
而上面调用的sync()方法,其实其内部会调用两个方法backwardPass()和forwardPass(),一个是逆推,一个是顺推,其实就是可以认为一个是正序,一个是倒序。 比如forwardPass(),其实其内部就是遍历刚才缓存Observer的集合,找到每个Observer
而这里的dispatchEvent,其实就是ObserverWithState的方法,因为ObserverWithState内部封装了LifecycleEventObserver对象,而LifecycleEventObserver对象又是封装了LifecycleObserver对象的。
比如Activity的,其实onStateChanged是在androidx.activity.ComponentActivity的构造器中添加注册的LifecycleEventObserver监听接收对应的处理回调,在这里就会根据是ON_STOP还是ON_DESTROY进行回调的处理,也就是生命周期的处理。 这样的生命周期回调,在自定义类实现LifecycleObserver接口的时候,也可以采用注解的方式注册对应的LifecycleEventObserver监听,这样的生命周期的回调,其实就是回调到对应的注解和事件的方法中。这样是采用了类似于apt注解处理器的方式,生成了对应的java类
这里需要注意,如果是自定义添加监听的时候,是实现了LifecycleEventObserver,那么在分发的时候,调用ObserverWithState的dispatchEvent方法去分发,就会直接回调到了自定义LifecycleEventObserver实现类中的onStateChanged中;而如果是使用LiveData添加观察者的话,则是封装成LifecycleBoundObserver对象,然后通过其onStateChanged方法继续进一步的处理分发,调用到对应的Observer的onChanged方法进行最终的处理
如果这里的分发是分发到上面的那个自定义的BasePresenter,则需要经过ReflectiveGenericLifecycleObserver
从上面的原理解析,可以知道,Lifecycle的生命周期的感知和分发,其实也是依赖于一个ReportFragment,这其实也是一个空的Fragment,这样的做法,其实与Glide的生命周期的监听是类似的做法,都是采用一个空的Fragment来监听生命周期的变化,然后在不同的生命周期做不同的操作。
Android Lifecycle源码解析
Lifecycle是生命周期的意思。它是Jetpack中的一个 生命周期感知型组件 ,可执行操作来感知响应另一个组件(如 Activity 和 Fragment)的生命周期状态的变化。
1.第一步添加依赖
2.实现LifecycleObserver接口以及添加注解
3.在Activity中或者Fragment中调用lifecycle.addObserver方法,把LifecycleObserver传入进去就可以
使用是不是很简单,在MytViewModelLifecycle里面就可以监听到Activity中或者Fragment生命周期了
1.首先分析lifecycle怎么来的 lifecycle调用的是ComponentActivity的getLifecycle方法,返回了一个mLifecycleRegistry
那么我们就从ComponentActivity入手会实现了它LifecycleOwner接口,并且初始化了LifecycleRegistry
2.addObserver分析 上面了解了lifecycle的实例,那么我们就从LifecycleRegistry入手,首先看addObserver方法,我们只管传入的参数哪里去了,也就是说我们只需要看ObserverWithState做了什么事. ObserverWithState会调用Lifecycling.lifecycleEventObserver方法,然后创建ReflectiveGenericLifecycleObserver对象,然后调用ClassesInfoCache.sInstance.getInfo,这个方法传入的是我们的MytViewModelLifecycle的对象,拿到他的class,然后通过反射拿到MytViewModelLifecycle方法和注解并且存入map.具体怎么反射这里就不细讲了! (在反射中一般都是通过map去存取提高性能)
3.观察者(MytViewModelLifecycle)是如何知道被观察者(Activity)的生命周期的 回到ComponentActivity中的onCreate方法,它会创建一个空白的ReportFragment,有了这个ReportFragment,当activity执行生命周期ReportFragment也会执行相应的生命周期. 我们以onStart为例,每个生命周期都会调用dispatch方法,最终都会调用**dispatch( Activity activity, Lifecycle.Event event)方法. 然后调用((LifecycleRegistry) lifecycle).handleLifecycleEvent(event)方法
在handleLifecycleEvent分别会调用getStateAfter和moveToState方法这两个方法,getStateAfter的目的就是通过生命周期得到一个状态.方便大家理解大家可以看白色背景的那张图.通过不同的事件拿到相应的状态 1.初始化状态-》页面显示状态,这种情况属于activity的创建到显示 这属于前进状态 2.页面显示状态-》销毁状态:这种情况下属于activity回到不可见了 这属于倒退状态
moveToState(next):这个方法的意思就是状态对齐.举个栗子吧:假如activity(被观察者)现在是onstart状态,这时候观察者MytViewModelLifecycle还是CREATE状态,这时候为了保证生命周期对齐,所以需要将next赋值给State,接着调用sync()进行同步
backwardPass方法 如果满足条件的主要调用downEvent 这个方法主要通过状态拿到事件,例如现在是STARTED对应上面的图拿到ON_STOP事件,然后又通过getStateAfter(ON_STOP)方法去拿到CREATED状态,
LifecycleEventObserver是一个接口 然后ReflectiveGenericLifecycleObserver实现了这个接口,所以最终调用了ReflectiveGenericLifecycleObserver的onStateChanged方法
invokeCallbacks方法里面通过反射拿到执行相应方法,这里就不多阐述了!
再回到sync()里面的forwardPass方法 如果满足条件的主要调用upEvent(observer.mState)拿到前进状态,例如现在是STARTED状态就可以到ON_RESUME事件通过ON_RESUME事件最终通过反射调用@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)的方法
总结一下: 1.ComponentActivity里面实现了LifecycleOwner接口 ,并且初始化LifecycleRegistry了,LifecycleRegistry是实现了LifecycleOwner接口 2.在ComponentActivity里面创建了一个透明的ReportFragment来感应activity的生命周期,在Fragment的生命周期方法里面分别执行对应的dispatch方法 2.addObserver方法创建了ReflectiveGenericLifecycleObserver并且存储了观察者的class信息, 3.在dispatch传入相应的事件之后,然后通过getStateAfter拿到相应的状态 4.通过状态枚举比大小,如果是倒退流程就调用backwardPass方法,backwardPass方法会通过downEvent拿到状态拿到事件,然后又通过事件拿到状态 5.,如果是前进流程就调用forwardPass方法,forwardPass方法会通过upEvent拿到状态拿到事件 6.最后在ReflectiveGenericLifecycleObserver.onStateChanged里面执行mInfo.invokeCallbacks执行相应的方法 7.之所以要设计状态 是要留给其他框架用的
LottieAndroid使用详解及源码解析—轻而易举实现各种复杂动画
我们主要从以下四个方面来讲解:
1、 编译版本需要 27 2、所有的suport包版本需要27.1.0
3、如果有引入lifecycle,版本需要1.1.0
安卓开发:如何得知当前activity是被压入后台,还是跳转到新的activity
最近学习安卓开发activity的生命周期,对单个活动的生命周期较为熟悉。此时师兄抛出问题,当一个activity进入 onStop() 时,如何得知时由于用户点击了主页键,还是由于进入了另一个本程序的activity? 查阅网络资源后,得知可以通过安卓本身的多种方法来判断。不过某些方法的使用需要获取用户授权,或者需要较高版本的安卓系统。不过本文主要介绍通过activity本身的生命周期回调函数来判断。 由于设计两个activity的跳转,所以我们应该去考虑多个activity的生命周期回调函数顺序。查阅并测试可知,当进行activity跳转时,先执行原来activity的 onPause() 和,然后执行第二个activity的 onCreate() 、 onStart() 、 onResume() ,再执行第一个activity的 onStop 。如图所示,红色是第一个activity的回调函数执行,蓝色是第二个。我们可以利用这个特点,通过一个static变量来记录当前run的activity数量,当这个数量为0的时候,即程序被压入后台,当这个数量不为0,则表明当前执行了一个跳转操作。 首先新建一个 BaseActivity 类,声明一个static变量,让别的activity全部继承。并在 onStart() 和 onStop() 中修改 count 。 创建 MainActivity 类,继承自 BaseActivity 类,同时修改 onStop() ,检查 count 的值,判断此次导致 onStop() 的原因。我在这个activity中添加了一个button用于跳转到第二个activity。 这个类很简单,没有什么功能,只是跳转过来后,执行基类的 onCreate() 方法。 至此,我们便实现了通过activity生命周期回调函数判断是否被压入后台。不过,后来学长针对我的这种方式提出了漏洞——当引用外部SDK,且外部SDK中可以弹出未继承我们自定义的base基类的activity,那么怎么处理这种情况呢?这里就要用到安卓SDK提供的全局生命周期类了——Application.registerActivityLifecycleCallbaks,这里我们之后再谈。
更多文章:
如何让Windows 10系统桌面变得更好看?win10桌面的简单美化
2024年7月26日 13:01
msvcr100 dll放哪里(msvcp100.dll丢失怎么办放在哪里)
2024年6月3日 02:32
星际争霸2手游单机版下载中文版(《星际争霸2》怎么玩单机的)
2024年6月13日 03:24
我的世界不一样(我想问一下,为什么我的手机网易版我的世界和别人主页都不一样)
2024年7月13日 16:54
s4 root教程(GALAXY S4 如何获取ROOT权限)
2023年6月18日 15:00
球球大作战刷棒棒糖(球球大作战怎么刷棒棒糖 拿棒棒糖有什么用)
2024年5月9日 17:05