launchMode解析
什么是任务栈
管理Activity进出顺序的栈,也叫回退任务栈(back task stack),当按下手机模拟键“返回”时将会依次弹出任务栈栈顶的Activity,直到该任务栈中所有的栈都退出,将会返回到主页。
TaskAffinity属性
定义该Activity所属任务栈,未填写该属性则默认加入到在当前包名的任务栈中。
SingleTask
1.singleTask:一个任务栈中只实现一个Activity实例,当已经有该Activity时清除在其上的所有Activity,并调用onNewIntent()方法
当用taskAffinity属性定义该Activity为其他包名时,将会在其他任务栈中创建该Activity,在该Activity中启动的Activity也将加入这个新建的Activity所属的任务栈,当其属于其他任务栈时回退栈就已经改变了。
这里有4种情况:
1.同一个应用中调用并加taskAffinity属性
2.同一个应用中调用不加taskAffinity属性
3.不同一个应用中调用并加taskAffinity属性
4.不同一个应用中调用不加taskAffinity属性
1.同一个应用中调用并加taskAffinity属性
在SecondActivity中修改launchMode和taskAffinity:
加入之后依次打开MainActivity->SecondActivity->ThirdActivity,其任务栈就有了两个:
TASK zzz.zz id=55
ACTIVITY com.lhq.launchmodedemo/.ThirdActivity 52752cb4 pid=17295
Local FragmentActivity 5273348c State:
mCreated=truemResumed=true mStopped=false mReallyStopped=false
mLoadersStarted=true
FragmentManager misc state:
mHost=android.support.v4.app.FragmentActivity$HostCallbacks@52733568
mContainer=android.support.v4.app.FragmentActivity$HostCallbacks@52733568
mCurState=5 mStateSaved=false mDestroyed=false
View Hierarchy:
...
ACTIVITY com.lhq.launchmodedemo/.SecondActivity 52719c98 pid=17295
Local FragmentActivity 52716590 State:
mCreated=truemResumed=false mStopped=true mReallyStopped=true
mLoadersStarted=true
FragmentManager misc state:
mHost=android.support.v4.app.FragmentActivity$HostCallbacks@5272d924
mContainer=android.support.v4.app.FragmentActivity$HostCallbacks@5272d924
mCurState=2 mStateSaved=true mDestroyed=false
View Hierarchy:
...
TASK com.lhq.launchmodedemo id=54
ACTIVITY com.lhq.launchmodedemo/.MainActivity 52756cc0 pid=17295
Local FragmentActivity 52717c84 State:
mCreated=truemResumed=false mStopped=true mReallyStopped=true
mLoadersStarted=true
...
可以看到有两个任务栈:zzz.zz和未定义taskAffinity而默认使用包名的任务栈com.lhq.launchmodedemo,在模拟器上的任务管理器中显示如下:
回退顺序:
zzz.zz栈:ThirdActivity->SecondActivity
com.lhq.launchmodedemo栈:MainActivity
2.同一个应用中调用不加taskAffinity属性
- 只有一个任务栈
TASK com.lhq.launchmodedemo id=14
:
TASK com.lhq.launchmodedemo id=14
ACTIVITY com.lhq.launchmodedemo/.ThirdActivity 52866e08 pid=6814
Local FragmentActivity 52764cd8 State:
mCreated=truemResumed=true mStopped=false mReallyStopped=false
mLoadersStarted=true
FragmentManager misc state:
mHost=android.support.v4.app.FragmentActivity$HostCallbacks@52764e20
mContainer=android.support.v4.app.FragmentActivity$HostCallbacks@52764e20
mCurState=5 mStateSaved=false mDestroyed=false
View Hierarchy:
...
ACTIVITY com.lhq.launchmodedemo/.SecondActivity 5282210c pid=6814
Local FragmentActivity 52731a78 State:
mCreated=truemResumed=false mStopped=true mReallyStopped=true
mLoadersStarted=true
FragmentManager misc state:
mHost=android.support.v4.app.FragmentActivity$HostCallbacks@52731b28
mContainer=android.support.v4.app.FragmentActivity$HostCallbacks@52731b28
mCurState=2 mStateSaved=true mDestroyed=false
View Hierarchy:
...
ACTIVITY com.lhq.launchmodedemo/.MainActivity 5285612c pid=6814
Local FragmentActivity 52729080 State:
mCreated=truemResumed=false mStopped=true mReallyStopped=true
mLoadersStarted=true
FragmentManager misc state:
mHost=android.support.v4.app.FragmentActivity$HostCallbacks@52729b50
mContainer=android.support.v4.app.FragmentActivity$HostCallbacks@52729b50
mCurState=2 mStateSaved=true mDestroyed=false
View Hierarchy:
...
任务管理器:
回退栈:ThirdActivity->SecondActivity->MainActivity
3.不同一个应用中调用并加taskAffinity属性
- 两个任务栈
TASK null id=26
ACTIVITY com.lhq.launchmodedemo/.ThirdActivity 52843f6c pid=29809
Local FragmentActivity 5275e538 State:
mCreated=truemResumed=true mStopped=false mReallyStopped=false
mLoadersStarted=true
FragmentManager misc state:
mHost=android.support.v4.app.FragmentActivity$HostCallbacks@5275e680
mContainer=android.support.v4.app.FragmentActivity$HostCallbacks@5275e680
mCurState=5 mStateSaved=false mDestroyed=false
View Hierarchy:
...
ACTIVITY com.lhq.launchmodedemo/.SecondActivity 52823538 pid=29809
Local FragmentActivity 52744200 State:
mCreated=truemResumed=false mStopped=true mReallyStopped=true
mLoadersStarted=true
FragmentManager misc state:
mHost=android.support.v4.app.FragmentActivity$HostCallbacks@52744348
mContainer=android.support.v4.app.FragmentActivity$HostCallbacks@52744348
mCurState=2 mStateSaved=true mDestroyed=false
View Hierarchy:
...
TASK com.lhq.launchmodedemo id=25
ACTIVITY com.lhq.launchmodedemo/.MainActivity 5282210c pid=29809
Local FragmentActivity 5272cfe8 State:
mCreated=truemResumed=false mStopped=true mReallyStopped=true
mLoadersStarted=true
FragmentManager misc state:
mHost=android.support.v4.app.FragmentActivity$HostCallbacks@5272dab8
mContainer=android.support.v4.app.FragmentActivity$HostCallbacks@5272dab8
mCurState=2 mStateSaved=true mDestroyed=false
View Hierarchy:
...
- 任务管理器:在未用图库应用调用起本应用时,就已经有两个任务栈了。当用图库调起SecondActivity时,不会再重新新建任务栈,而是把SecondActivity移动到栈顶。
- 回退任务栈:SecondActivity->桌面
4.不同一个应用中调用不加taskAffinity属性(通过图库调起,后面的不同引用调用也是指图库)
- 一个任务栈
TASK com.lhq.launchmodedemo id=290
ACTIVITY com.lhq.launchmodedemo/.SecondActivity 101b9a9 pid=23559
Local FragmentActivity e934f4d State:
mCreated=truemResumed=true mStopped=false mReallyStopped=false
mLoadersStarted=true
FragmentManager misc state:
mHost=android.support.v4.app.FragmentActivity$HostCallbacks@d6e782d
mContainer=android.support.v4.app.FragmentActivity$HostCallbacks@d6e782d
mCurState=5 mStateSaved=false mDestroyed=false
View Hierarchy:
...
ACTIVITY com.lhq.launchmodedemo/.MainActivity aea3932 pid=23559
Local FragmentActivity ecd2145 State:
mCreated=truemResumed=false mStopped=true mReallyStopped=true
mLoadersStarted=true
FragmentManager misc state:
mHost=android.support.v4.app.FragmentActivity$HostCallbacks@3a6e0e0
mContainer=android.support.v4.app.FragmentActivity$HostCallbacks@3a6e0e0
mCurState=2 mStateSaved=true mDestroyed=false
View Hierarchy:
...
- 任务管理器:没有新建任务栈
- 回退栈:在原应用中回退:SecondActivity->MainActivity
singleTask总结
2.当其他应用调用到该singleTask的Activity时:
1.当该Activity已启动,并在后台通过其他应用启动不会再构建任务栈,而是在原任务栈的基础上将该singleTaskActivity上的其他Activity都清除
2.当该Activity未启动时,将新建任务栈并将该Activity置于栈底
只需要注意,当加上了taskAffinity属性,且指定了不同的包名,就会将Activity加入到新建任务栈,只需要理解了任务栈是栈的形式存储和弹出Activity就能知道它的回退顺序。
singleInstance
和singleTask类似一个任务栈一个实例,启动另一个任务栈,但是区别是从该Activity启动的其他Activity和它并不属于一个任务栈。
这个launchMode我们分两种情况讨论:有无taskAffinity属性,而在其他应用启动singleInstance Activity的情况就不说了,看完下面的测试就明白了
1.未定义taskAffinity:
TASK com.lhq.launchmodedemo id=87
ACTIVITY com.lhq.launchmodedemo/.ThirdActivity 529c3dd8 pid=30275
Local FragmentActivity 5271db68 State:
mCreated=truemResumed=true mStopped=false mReallyStopped=false
mLoadersStarted=true
FragmentManager misc state:
mHost=android.support.v4.app.FragmentActivity$HostCallbacks@5271dc7c
mContainer=android.support.v4.app.FragmentActivity$HostCallbacks@5271dc7c
mCurState=5 mStateSaved=false mDestroyed=false
View Hierarchy:
...
ACTIVITY com.lhq.launchmodedemo/.MainActivity 527cb71c pid=30275
Local FragmentActivity 52716150 State:
mCreated=truemResumed=false mStopped=true mReallyStopped=true
mLoadersStarted=true
FragmentManager misc state:
mHost=android.support.v4.app.FragmentActivity$HostCallbacks@52716cb0
mContainer=android.support.v4.app.FragmentActivity$HostCallbacks@52716cb0
mCurState=2 mStateSaved=true mDestroyed=false
View Hierarchy:
...
TASK com.lhq.launchmodedemo id=88
ACTIVITY com.lhq.launchmodedemo/.SecondActivity 527f5e18 pid=30275
Local FragmentActivity 52714b34 State:
mCreated=truemResumed=false mStopped=true mReallyStopped=true
mLoadersStarted=true
FragmentManager misc state:
mHost=android.support.v4.app.FragmentActivity$HostCallbacks@52727970
mContainer=android.support.v4.app.FragmentActivity$HostCallbacks@52727970
mCurState=2 mStateSaved=true mDestroyed=false
View Hierarchy:
...
- 任务管理器中却只有一个任务:
- 回退栈:ThirdActivity->MainActivity->SecondActivity->桌面
这里有个细节:当我依次打开三个Activity,然后将该任务栈置于后台(也就是非可见的状态,比如回到主页)时,再次进入该应用,再次按返回弹出任务栈时,它的弹出顺序变了:ThirdActivity->MainActivity->桌面,这个就很奇怪,但是我查看过任务栈列表,SecondActivity在我回到该应用时还在,但是在回退中再也无法启动到SecondActivity,原因我也没搞清楚,所以这种形式的singleInstance Activity不建议使用。
2.定义taskAffinity:
TASK com.lhq.launchmodedemo id=106
ACTIVITY com.lhq.launchmodedemo/.ThirdActivity 52750184 pid=11450
Local FragmentActivity 5273cb94 State:
mCreated=truemResumed=true mStopped=false mReallyStopped=false
mLoadersStarted=true
FragmentManager misc state:
mHost=android.support.v4.app.FragmentActivity$HostCallbacks@5273cc60
mContainer=android.support.v4.app.FragmentActivity$HostCallbacks@5273cc60
mCurState=5 mStateSaved=false mDestroyed=false
View Hierarchy:
...
ACTIVITY com.lhq.launchmodedemo/.MainActivity 52a6de0c pid=11450
Local FragmentActivity 52713d68 State:
mCreated=truemResumed=false mStopped=true mReallyStopped=true
mLoadersStarted=true
FragmentManager misc state:
mHost=android.support.v4.app.FragmentActivity$HostCallbacks@527148c8
mContainer=android.support.v4.app.FragmentActivity$HostCallbacks@527148c8
mCurState=2 mStateSaved=true mDestroyed=false
View Hierarchy:
...
TASK zzz.zz id=107
ACTIVITY com.lhq.launchmodedemo/.SecondActivity 52739af8 pid=11450
Local FragmentActivity 5274c0ac State:
mCreated=truemResumed=false mStopped=true mReallyStopped=true
mLoadersStarted=true
FragmentManager misc state:
mHost=android.support.v4.app.FragmentActivity$HostCallbacks@5274c1f4
mContainer=android.support.v4.app.FragmentActivity$HostCallbacks@5274c1f4
mCurState=2 mStateSaved=true mDestroyed=false
View Hierarchy:
...
有两个任务栈zzz.zz和com.lhq.launchmodedemo,同时在SecondActivity中启动的ThirdActivity加入到了com.lhq.launchmodedemo id=106的栈中,zzz.zz id=107任务栈只有SecondActivity一个。
看模拟器中的任务管理器中显示的任务个数,理论上说应该是2个(确实是两个):
回退栈:各栈各自回退,ThirdActivity->MainActivity->桌面
SecondActivity->桌面
singleTask和singleInstance对比:
同:栈中只能有一个实例,当定义了taskAffinity属性时将会形成新的任务栈,且能显示在任务管理器中
异:在singleTask Activity中启动其他的Activity会加入到该singleTask Activity所在的栈中,而singleInstance Activity所在的栈中只有该Activity,即使在该Activity中启动其他Activity也不会再加入到该栈中,而是加入到其他栈中去。
Activity onNewIntent()的使用
1.除了standard模式之外都有可能调用到该方法,最好的办法就是在onCreate()方法和onNewIntent()方法中调用同一个处理数据的方法。
调用到的顺序:onNewIntent()->onStart()->onResume()
而在Activity中也有一个方法setIntent(intent)将会覆盖原来的intent,然后可以通过getIntent()方法获取最新的intent。可以查看Activity中的源码,最好用setIntent()来设置Intent,然后在其他方法中通过getIntent()获取intent对象。这样能尽可能的解藕。
应用
singleTop:通知内容显示详情的页面,导航页在进入主页时点击过快有时会形成两个主页面,也可以用singleTop,但是用singltTask会比较建议
singleTask:App的主界面
singltInstance:(不建议使用)拨号界面就是singleInstance实例
demo地址:https://github.com/Adam0407/LaunchModeDemo
参考:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0520/2897.html