安卓Fragment框架项目源码(安卓框架原理)
今天给各位分享安卓Fragment框架项目源码的知识,其中也会对安卓框架原理进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!
本文目录一览:
- 1、Android-ViewPager源码解析与性能优化
- 2、FragmentFactory源码浅析
- 3、Android Fragment 开发框架合集
- 4、Android的Fragment源码中为什么要调用setClassLoader
Android-ViewPager源码解析与性能优化
ViewPager高度设置为wrap_content或者具体的高度值无效,是因为ViewPager的onMeasure方法在度量宽高的时候,在方法体的最开始就直接调用了setMeasuredDimension()方法将自身的宽高度量,但是并没有在其onMeasure()计算完其具体的子View的宽高之后,重新度量一次自身的宽高
从这里我们可以看到,ViewPager的宽高会受其父容器的宽高的限制,但是并不会因为自身子View的宽高而影响ViewPager的宽高。
看setMeasuredDimension的源码调用可以看出,当父容器的高度确定时,ViewPager的宽高其实就是父容器的宽高,ViewPager就是在onMeasure方法一进来的时候就直接填充满整个父容器的剩余空间。在计算孩子节点之前,就已经计算好了ViewPager的宽高,在计算完孩子节点之后,并不会再去重新计算ViewPager的宽高。
自定义一个ViewPager,根据子View的宽高重新度量ViewPager的宽高。其实做法就是在自定义onMeasure的super.onMeasure(widthMeasureSpec, heightMeasureSpec);之前重新计算heightMeasureSpec,将原本ViewPager接收的父容器的限定的heightMeasureSpec替换成我们自定义的heightMeasureSpec。
但是这样的做法,会有种问题,即在ViewPager的子View是采用LinearLayout作为根布局的时候,并且给LinearLayout设置了固定的高度值,那么会出现ViewPager动态高度无效的问题
其实具体的做法,就是仿造measureChild的做法,自定义子View的heightMeasureSpec然后度量整个子View,其实子View的宽度也可以这样做。
这里其实是源码层做了限制,在setOffscreenPageLimit中设置了一个默认值,而这个默认值的大小为1
所以从这里可以看出,ViewPager的最小缓存的limit是1,而不能小于1,当小于1的时候就会被强制的设置为1。
而populate()函数就是用来处理ViewPager的缓存的。
populate()的生命周期是与Adapter的生命周期绑定的。
其实在setOffscreenPageLimit()的时候,调用的populate(),而populate()内部调用的
而pupulate(int newCurrentItem)方法在另一处调用的地方就是在setCurrentItem。
其实ViewPager缓存都是基于ItemInfo这个类来进行的,
看下ViewPager.addNewItem的源码
其实ViewPager.addNewItem就是通过调用Adapter.instantiateItem来创建对应的View,并且将View保存到ItemInfo中的object属性,并且判断ViewPager缓存中是否已经有ItemInfo,如果没有,则添加,如果有则做修改替换
从分析FragmentStatePagerAdapter来看,setUserVisibleHint方法会优先于Fragment的生命周期函数 执行。因为在FragmentStatePagerAdapter中提交事务,是在调用finishUpdate方法中进行的,只有提交事务的时候,才会去执行Fragment的生命周期。
FragmentStatePagerAdapter中的instantiateItem和destroyItem都实现了对fragment的事务的添加和删除,而finishUpdate实现了事务的提交,所以在实现FragmentStatePagerAdapter的时候,并不需要重写instantiateItem和destroyItem
FragmentFactory源码浅析
本文主要分析 FragmentFactory 编写前后对比,以及简单的 FragmentFactory 使用
FragmentFactory 主要用于 Fragment 的初始化,但是 FragmentFactory 并非强制使用的.默认无参的 Fragment 构造函数可以不使用 FragmentFactory ,否则还是建议使用 FragmentFactory 来进行实例化. [2]
FragmentFactory最重要的方法 FragmentFactory#instantiate(ClassLoader, String) ,源码方法很短.
使用方法就是继承 FragmentFactory 之后重写 FragmentFactory#instantiate(ClassLoader, String) 即可. [1]
没有 FragmentFactory 之前,是简单直接粗暴调用 Fragment#instantiate(@NonNull Context context, @NonNull String fname) 就算. 不过很多时候开发者写的 Fragment 都会写一个 static 的 newInstance(params:object) 方法去实例化,当状态恢复的时候,直接调用 Fragment#instantiate(@NonNull Context context, @NonNull String fname) 就会出错 -- InstantiationException ,所以才有了 FragmentFactory + FragmentManager#getFragmentFactory() 的搭配使用.
如下图所示,可以通过给 FragmentManager 传入一个 FragmentFactory 的对象(这里有个坑,下面会说到),之后对接下来的 Fragment 做带参实例化处理,如果 Fragment 可以无参实例化的话,可以不使用 FragmentFactory .
然后在需要的地方调起 fm.getFragmentFactory().instantiate(context.getClassLoader(), name) ,
e.g. FragmentManager#restoreSaveState(state) , FragmentContainerView(context,attrs,fm) , FragmentTabHost#doTabChanged( tag, FragmentTransaction)
上面 提到,其实每个 FragmentManager 只有一个 FragmentFactory 的对象,而 activity 也是只有一个 FragmentManager . 所以如果是那种 [一个Activity多个业务Fragment] 的模式,而且业务Fragment都在不同module以及不同framework的话,就不能够每个framework设置一个 FragmentFactory 了,否则就能够给其中一个framework使用了.如果打算每个framework设置一个 FragmentFactory ,之后Activity的 FragmentFactory 遍历各个framework的 FragmentFactory 也是不行的, 因为 FragmentFactory 的源码决定了, 如果找不到Fragment就会报错 , 当然也可以在 else 的时候,不调用 super.instantiate(classLoader, className) ,不过这样在团队开发的时候容易出错,造成APP crash.
为了解决这个问题,只能够把 FragmentFactory 放到Activity做扩展,在各个framework实现不同的delegate.
Android Fragment 开发框架合集
一个强大的 Fragment 管理框架,为"单 Activity + 多 Fragment ","多模块 Activity + 多 Fragment "架构而生,简化开发,轻松解决动画、嵌套、事务相关等问题。
一个强大的Fragment管理框架。
这可能是使用成本最低的 Fragment 框架。
无需继承!!!无需继承!!!无需继承!!! 重要的话说三遍!!
在使用 FragmentRigger 的时候,使用成本只有一行注解!!!
原理: 是把 Fragment / Activity 生命周期相关方法定义为切点,通过 ASpectJ 绑定并使用代理类进行操作。
一个可以管理 Fragment 嵌套,状态栏和 Toolbar 透明的库。
可以能用构造一个 Activity 框架。
一个封装了启动模式的 Fragment 便捷使用库,方便构建单 Activity + 多 Fragment 轻量级框架。
FragmentMaster 是一个库,允许您轻松开发仅由 Fragments 导航的 Android 应用程序。
Fragmentation 可以使用接口实现Base类的方便扩展,功能也相当强大还支持 EventBus
FragmentRigger 使用了注解来实现框架,可能需要注意冲突
FragmentStack 相当轻量,适合比较简单的需求使用
Android的Fragment源码中为什么要调用setClassLoader
查看Bundle源码及ClassLoader原理,因为每个Android应用都会有一个单独的虚拟机实例,如果A进程的Bundle传递到B进程,B进程需要加载Bundle中对应的Object,则需要A进程的ClassLoader来加载A进程中的class,不知道我的理解是否正确。
安卓Fragment框架项目源码的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于安卓框架原理、安卓Fragment框架项目源码的信息别忘了在本站进行查找喔。