关于Android Activity启动的flag和启动模式
最近因为项目需求当中,需要按一个按键,退回到指定的Activity,有可能是连续退几个Activity,第一时间想到的是多写几个finish()......然后想想就不可能,查了下Activity的相关资料,假如需要回退到Activity A,那么把A的启动模式设置为singleTask,然后startActivity启动A就可以了,在Manifest.xml中A的声明里面加上一句话,Android::launchmode ="singleTask",当然这样会导致每次启动A的时候都会,先检查这个包名的activity栈里面有没有有A,如果有就会清除掉栈中A上面的所有Activity(会依次导致各个被摧毁的Activity的onDestroy函数的调用),如果没有则会创建一个新的A放在栈顶。
这样写确实是没有问题的,因为顺便看到了一些Activity的flags,所以看了下,觉得似乎FLAG_ACTIVITY_CLEAR_TOP也可以做到这样的效果,考虑到大家好像都和FLAG_ACTIVITY_NEW_TASK一起用,虽然看文档觉得FLAG_ACTIVITY_NEW_TASK是多余的,但是也考虑到假如回退的Activity不存在的情况下.....凑合一下吧,于是就有了:
Intent intent = new Intent(this,A.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
然后崩溃开始了。。查了好久才发现:
FLAG_ACTIVITY_CLEAR_TOP: 假如已经存在了一个能够响应此intent的activity类型的实例,则这个实例之上的所有activity都将被清理以使它位于堆栈的顶部来对intent做出响应。如果此时指定的activity的加载模式为“standard
”(即默认情况下),则它本身也会从堆栈中移除,并加载一个新的实例来处理到来的intent。这是因为加载模式为“standard
”的activity总会创建一个新实例来处理新的intent。也就是,这种情况下,A会先销毁再创建,因此假如重写了A的onDestroy方法,释放资源的话,会导致两次释放资源的问题,如果我们设置加载模式为singleTask,则也不需要addFlags了,直接启动就可以了。。。顺便贴一下:
FLAG_ACTIVITY_NEW_TASK
: 如果已经存在了一个与新activity有着同样affinity的任务,则activity会载入那个任务之中。如果没有,则启用新任务。
另外由相关的博文也联想到,我们也可以在Application的子类中建立一个list对Activity进行管理,主要方法是实现ActivityLifecycleCallbacks,也可以注册这个回调,重写OnActivityCreated,OnActivityDestroy方法,分别对应list.add, list.remove方法,当我们需要返回到某个特定的Activity的时候,可以在list中对它上面的Activity进行一个个finish(),具体还没有验证,因为直接设置Android::launchmode ="singleTask"比较简单,呵呵~
另外,我之前把启动的MainActivity设置为singleTask的时候,程序切换出去再切换回来出现了始终打开MainActivity的情况,最后只好在MainActivity前面再加了一个Activity,这样就正常了。。
===============150829更新
昨天重写了onDestroy方法,因为系统偷偷销毁再重启你的Activity的情况实在是太多。。所以重写主要是为了系统偷偷这样做的时候不会导致程序出现意外,比如我之前在ondestroy里面写了退出登录,释放session,释放video,audio资源等,现在都换到别的地方去了,至于这样做有没有问题。。有待测试部的妹子的确认。。。。