• 一行代码,完成多层视图回退功能(android)

    01/11 樱桃 1 评论

其实是我做了个开源项目(*^__^*),拿出来给大家鉴赏下,欢迎大家提意见
项目:https://github.com/xuyt11/androidBackFlow 欢迎关注和star。
功能:一个控制Android视图(activity与fragment)回退的工具。
tip:这是一个回退工具,不是跳转工具

现在的开发同学应该对产品的需求有蛮多体会,就是好好的业务流程,在经过多次发版之后,从树形变成了网状,就算是自己写的,只要时间隔久了也要仔细的去阅读代码,才能再次小心翼翼的去修改。

现在的痛点
业务流程的回退功能:
需要提前finish或者finish几个页面。
在逻辑判断的时候,要去设置状态值,用setResult来finish多个页面。…

各种各样的多视图回退,造成了复杂的视图跳转逻辑。且这样造成了在回退过程中的多个视图,都有状态的判断逻辑。
所以,如果有一个工具,能够在我们需要回退的时候,就能回退到目标视图,将会降低代码的复杂及提高我们开发的速度。

解决思路
1. 原来的回退视图功能,我们主要利用的是startActivityForResult、onActivityResult、setResult与finish(activity)来进行实现的。
所以,如果我们每一次都是调用的startActivityForResult方法,而不是startActivity,那我们不就可以使用onActivityResult、setResult与finish(activity),来进行链式的视图回退了!
2. 如何回退到指定的activity或fragment呢!
我们可以知道回退的activity与fragment的class类型,所以只要我们可以在Activity的onActivityResult方法中判断当前activity与其中管理的fragments,就能够在指定视图不再执行finish方法,从而让指定视图显示出来
activity的判断:
在Activity的onActivityResult方法中,我们能判断当前Activity的Class类型;
activity中fragment的判断:
在Activity的onActivityResult方法中,我们能通过getSupportFragmentManager().getFragments()方法,获取到管理的fragments,从而判断fragment的的Class类型;
fragment中的fragments的判断:
这些fragment也能通过getChildFragmentManager().getFragments()方法获取到。
3. 若在固定顺序的业务流程中,我想要按照activity界面的position来进行回退呢!
在固定顺序的业务流程中,每个activity都有固定的position,所以只要计算position的差值(即backActivityCount),我们可以在onActivityResult方法中,回退数量为backActivityCount个的Activity,就可以了。

如何优雅的退出App?这样优雅的退出App!

当然,这是有限制的(。﹏。),只是退出当前的task而已! finish_task.gif

下面是androidBackFlow的详细介绍

简介
1. 这是一个链式回退多层视图的工具。
1. 这是一个在single task && single process环境中使用的工具。
2. 若app中有多个task或process,则只能在task或process之中使用,不能超过其中任何一个的范围。
3. task与task,task与process,process与process之间的回退功能,需要自己或系统去控制。
4. 若在task中有消耗过onActivityResult方法的情况,则BackFlow会失效。

快速使用
1. 使用前:
* 将App中所有的activity与fragment都继承于两个基础类(BaseBackFlowActivity与BaseBackFlowFragment)
* 或将app的基础类继承于两个基础类(BaseBackFlowActivity与BaseBackFlowFragment)
* 或在自己的基础类中@override startActivity与onActivityResult,并添加startActivity4NonBackFlow方法;

2. 结束该activity所属的task:
* 若该App是单task的,则有结束App中所有的activity效果(finish该task中所有的activity,即退出了App)
* 若在整个回退流程流程中,没有匹配到目标,也相当于finish_task的功能。
* 若中间有onActivityResult方法被消耗,则会停留在最后一个被消耗的activity(因为setResult已无效)。

* 效果

<image title=’finish task’ alt=’finish task.gif’ width=200 src=’https://github.com/xuyt11/androidBackFlow/raw/master/screen/finish_task.gif’ />

3. 返回到指定的activity(回退到指定的activity),若有多个activity实例,则只会回退到第一个匹配;

4. 返回到指定的fragment列(回退到第一个匹配该fragment顺序列的activity,会调用fragments中最后一个fragment的onActivityResult)

* 效果
![request_fragments.gif](https://github.com/xuyt11/androidBackFlow/raw/master/screen/request_fragments.gif “request fragments”)
5. 返回到activity和fragment列都一致的activity(回退到包含了该fragment顺序列的activity,会调用fragments中最后一个fragment的onActivityResult)

* 效果
![request_activity_fragments.gif](https://github.com/xuyt11/androidBackFlow/raw/master/screen/request_activity_fragments.gif “request activity fragments”)
6. 回退数量为backActivityCount个的Activity

7. 若有额外参数,可以使用带Bundle参数的request方法

8. 也可以自己去使用Builder去构建BackFlow request

tip
* fragment的sub fragment manager必须要是getChildFragmentManager
* BackFlow内部的Fragment是support-v4包中的,若app中使用的不是android.support.v4.app.Fragment,则可以将其替换为你自己的Fragment类型
* 若你内部的Fragment有多个基础类型(android.support.v4.app.Fragment, android.app.Fragment),那你需要统一
* 若跳转目标View是Fragment,则该Fragment的ParentFragment是不会调用到onActivityResult方法的

BackFlow不能使用的情况或不能回退到目标位置
1. 若在回退链中间有任何一个XXXActivity消耗过onActivityResult方法,则会停留在该XXXActivity,不能继续回退
* 因为整个回退功能都是依赖于setResult方法将回退数据,链式的传递给前一个activity的onActivityResult方法,而在activity消耗了onActivityResult方法之后,是不会再调用该方法的。
2. 现在发现的消耗onActivityResult方法的情况有:
* 切换task;
* 切换process;
* 在startActivity时,调用了intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3. launchMode
* 不同的android版本,有不同的区别;4.4会消耗,5.0.2与6.0不会消
* singleInstance
* 会启用一个新的栈结构,将Acitvity放置于这个新的栈结构中,并保证不再有其他Activity实例进入
* 4.4会切换task
* **5.0.2与6.0 startActivityForResult时不会切换task,所以仍然可以使用,不过这时launchMode将变为standard**
* singleTask
* 4.4会消耗onActivityResult方法
* 5.0.2与6.0 startActivityForResult时不会回调onActivityResult,所以仍然可以使用,不过startActivityForResult方法,这时由于launchMode将变为standard

tips and limitations (提示与限制)
1. launchMode: startActivityForResult启动singleTop, singleTask, singleInstance的XXXActivity
* 5.0之后的系统,则XXXActivity的launchMode设置失效,变为standard launchMode
* 5.0之前的系统,只有singleTop模式失效
* 所以,若有需求的话,则可以使用startActivity4NonBackFlow方法,不过这时候BackFlow将失效,将会停留在该处不再回退
2. startActivityForResult + Intent.FLAG_ACTIVITY_NEW_TASK + singleInstance,会启动一个新task,所以BackFlow将失效,将会停留在该处不再回退

3 1 收藏


直接登录
最新评论
  • acjiji   01/16

    共享一个开源控件,给自己做个小广告,共享一个开源的自定义的控件—-表盘,适合大量数据的展示,底层使用的RecyclerView实现,同样提供Adapter来加载数据,支持向前和向后加载更多,使用简单,欢迎有需要的人提出宝贵意见:https://github.com/zhouchaoyuan/excelPanel