基于AOP设计的Fragment框架

文章讲述了在使用Fragment时遇到的常见问题,如内存重启后的Fragment问题、事务提交、懒加载、onBackPressed监听等,并介绍了FragmentRigger框架如何简化这些问题的解决,通过API增强和优化Fragment的使用体验。
摘要由CSDN通过智能技术生成
  • 屏幕翻转时(内存重启)后Fragment遇见的问题
  • 在一个ContainerView中添加两个Fragment,第一个Fragment还可以被点击问题
  • 提交事物后无法立即执行导致的各种问题

难点三: 其他问题

  • 无法监听onBackPressed
  • 在ViewPager中使用懒加载
  • Fragment多层嵌套时入栈出栈问题
  • Fragment事物提交失败
  • 多个Fragment同时入栈/出栈问题

上述只是在使用Fragment中遇到的部分问题,种种恶行,罄竹难书!!! 但是这些问题都在FragmentRigger中被解决了!!!

2、解决方案

那么这些问题是如何解决的呢?由于篇章限制,下面列举几个特别常见的问题的解决方法。

已解决:Can not perform this action after onSaveInstanceState

我们先来看看这个异常的抛出的出处,这是在FragmentManager中被抛出的,源码如下:

private void checkStateLoss() {
if (mStateSaved) {
throw new IllegalStateException(
“Can not perform this action after onSaveInstanceState”);
}
}

而这个方法是在方法enqueueAction(Runnable,boolean)中被调用的,调用代源码如下:

public void enqueueAction(Runnable action, boolean allowStateLoss) {
if (!allowStateLoss) {
checkStateLoss();
}
}

这个方法会在提交事物的时候调用,并且参数也是在那时候传递的,所以,使用commitAllowingStateLoss方法确实可以避免该异常的抛出,但是这次提交可能丢失,所以这并不是最好的解决方案。 使用该方法只能说是避免异常,并不是解决异常!!!

所以要解决该异常,我们需要知道mStateSaved方法是什么时候被置为true ,通过源码分析(请自行分析,此处对分析过程不进行阐述),发现mStateSaved会在Activity#onStop调用时被置为true。而onSaveInstanceState是在onStop之前被调用的,那么这个错误的意思也是没毛病的。
那么我们如何解决这个问题呢,Activity生命周期中onSaveInstanceState方法之前执行的是onPause方法,所以我们只需要判断onPause是否被执行,并在已经被执行的时候不进行事物提交即可!!! 贴心的是在Fragment中提供了方法isResumed()可以判断该状态,我们可以手动在Activity中实现该方法。
那么最终解决方案就是:在Activity/Fragment非onResume的状态下不要提交事物,保存下来,在onResum的情况下重新提交,就可以确保事物一定提交成功,并且不会丢失!!!

已解决:Fragment重叠显示

Fragment重叠显示的原因就很明显了,多个Fragment被add在同一个container中,并且都是show的状态,所以会导致重叠!!! 这个的解决方案YoKeyword的文章《9行代码让你App内的Fragment对重叠说再见》中已经解决,就不在此进行重复了。

已解决:无法监听onBackPressed

这个问题相比是大多数人都有的需求,但是奈何Fragment中并没有该方法的支持,所以我们只能手动去实现该功能。
解决方案:在Fragment中定义方法onBackPressed,并在Activity中遍历所持有的Fragment并对该方法进行调用。
一切看似很简单,但是时候存在一系列新的问题,如:在Fragment入栈之后多级嵌套后的传递顺序问题、在栈内该方法的拦截问题等。 实现起来成本还是很大的。不过,在FragmenTRigger 中这个问题得到了合理的解决。

已解决:在ViewPager中使用懒加载

ViewPager为我们提供了预加载的机制,但这种机制在使用的时候有时候反而不是好事,如果我们通过setOffscreenPageLimit设置的条目少了会让在切换的时候重新生成Fragment实例,但要是添加的多了则会让好多Fragment同时被初始化,所以此时,使用懒加载可以有效处理该场景,只有在显示的时候进行数据加载等行为,并且在正常情况下只加载一次。
那么我们如何在ViewPager中加入懒加载呢?通过源码分析,ViewPager是通过setUserVisibleHint(boolean)来控制Fragment是否显示的,所以我们可以在Fragment中重写该方法,并根据传入的boolean值判断Fragment是否显示的状态,但是需要注意的是,我们需要进行Fragment是否手机加载的判断进行是否懒加载的调用,否则,ViewPager每次切换都会调用setUserVisibleHint
解决方案:在Fragment中重写setUserVisibleHint()方法,并且定义一个懒加载的方法如:onLazyLoad(),根据setUserVisibleHint()传入的值判断Fragment是否显示,并调用懒加载方法。
样例代码如下:

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
if (!mHasInitView||!isVisibleToUser) return;
//make sure the method onLazyViewCreated will be called only once.
if (mHasInvokeLazyLoad) return;
onLazyLoad();
}

当然,上述只是伪代码,不过进行懒加载的原理就是这样。

三、上勾

上面列举了部分Fragment在使用过程中遇到的问题给给出部分解决方案,看上去好像是这么解决的啊,所以,我不是骗子啦~接下来正式对框架FragmentRigger进行介绍。

一个强大的Fragment框架,目标:让Fragment的使用更简单!!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这可能是使用成本最低的Fragment框架了。
无需继承!!!无需继承!!!无需继承!!! 重要的话说三遍!!
在使用FragmentRigger的时候,使用成本只有一行注解!!!
原理是把Fragment/Activity生命周期相关方法定义为切点,通过ASpectJ绑定并使用代理类进行操作。

1、Wiki

2、特性

  • 超强大Api支持
  • 足够多的英文注释
  • 严格的异常抛出
  • 解决Fragment中常见的异常及Bug
  • 事务提交永不丢失
  • 扩展原生方法,添加`onBackPressed`等常见的方法支持
  • 当前栈成员树状图打印
  • Fragment懒加载
  • Fragment转场动画
  • Fragment间共享元素转场动画(TODO)
  • Kotlin支持(TODO)

3、解决的问题

  • Fragment界面重叠
  • Fragment多级嵌套
  • Fragment栈的管理问题
  • Fragment事务提交失败
  • Activity在非onResume状态下提交事务
  • Fragment事务提交不能立即执行导致两次提交事件冲突
  • `内存重启`时的一系列异常
  • 屏幕翻转时的数据保存及恢复
  • ~Can not perform this action after onSaveInstanceState~
  • 在ViewPager中的懒加载及其他场景下的懒加载
  • 不同场景下转场动画不执行问题

4、Demo演示

栈管理懒加载同级显示
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
支持Fragment同级\多层嵌套,并提供返回自动显示栈顶成员等一系列场景支持支持ViewPager等场景下的懒加载机制,使用简单,一行注解就可以支持通过show方法显示Fragment,支持预加载,懒加载等场景

为了保持篇章的简洁和美观性,其他的场景具体请在项目中查看!!!

5、超强大Api支持演示

本框架在开始的时候就声明强大的Api支持,那么本节举例几个场景。

场景一: Fragment懒加载

在前面也对懒加载提出了相应的解方案,那么在本框架中是怎样使用的呢?请看下面代码:

@LazyLoad
@Puppet
public class ContainerFragment extends Fragment{
public void onLazyLoadViewCreated(Bundle savedInstanceState) {
//do something in here
}
}

使用成本: 两行注解,一个方法,不需要继承父类!!!

场景二: 转场动画

Fragment为我们提供了转场动画机制,但是在使用的时候需要和事物提交一起使用,并且在remove的时候不支持转场动画。

@Animator(enter=R.anim.enter,exit=R.anim.exit,popEnter=R.anim.popEnter,popExit=R.anim.popExit)
@Puppet
public class AnimatorFragment extends Fragment{
}

使用成本: 两行注解,一个方法,不需要继承父类!!!
那么问题来了,如何在library使用该注解呢,因为在library中R中的资源id都是变量,无法直接在注解中使用,本框架对此也进行了相应的解决方案。

@Puppet
public class AnimatorFragment extends Fragment{
public int[] getPuppetAnimations(){
return new int[]{
R.anim.enter, R.anim.exit, 0, 0
};
}
}

不需要支持某场景的转场动画就置为0,但是返回参数必须为长度为4的int数组。无需继承,直接添加该方法即可!!!

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

写在最后

对程序员来说,很多技术的学习都是“防御性”的。也就是说,我们是在为未来学习。我们学习新技术的目的,或是为了在新项目中应用,或仅仅是为了将来的面试。但不管怎样,一定不能“止步不前”,不能荒废掉。

![
[]


文章以下内容会给出阿里与美团的面试题(答案+解析)、面试题库、Java核心知识点梳理等

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!

转存中…(img-mXQwFMLg-1712388796073)]
[外链图片转存中…(img-rZiCYsSi-1712388796073)]

文章以下内容会给出阿里与美团的面试题(答案+解析)、面试题库、Java核心知识点梳理等

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值