Activity四大启动模式

ctivity的四种启动模式:

standard、singleTop、singleTask、singleInstance

为了打印方便,定义一个基础Activity,在其onCreate方法和onNewIntent方法中打印出当前Activity的日志信息,主要包括所属的task,当前类的hashcode,以及taskAffinity的值。之后我们进行测试的Activity都直接继承该Activity

package com.lyf.launchmodektdemo

import android.content.Intent
import android.os.Bundle
import android.view.MenuItem
import androidx.appcompat.app.ActionBar
import androidx.appcompat.app.AppCompatActivity

open class BaseActivity : AppCompatActivity() {
lateinit var actionBar: ActionBar

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

actionBar = supportActionBar!!
actionBar?.setDisplayHomeAsUpEnabled(true)

printTaskInfo(this, "onCreate")
dumpTaskAffinity(this)
}

override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
printTaskInfo(this, "onNewIntent")
dumpTaskAffinity(this)
}

override fun onRestart() {
super.onRestart()
printTaskInfo(this, "onRestart")
}

override fun onStart() {
super.onStart()
printTaskInfo(this, "onStart")
}

override fun onResume() {
super.onResume()
printTaskInfo(this, "onResume")
}

override fun onPause() {
super.onPause()
printTaskInfo(this, "onPause")
}

override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
printTaskInfo(this, "onSaveInstanceState")
}

override fun onStop() {
super.onStop()
printTaskInfo(this, "onStop")
}

override fun onDestroy() {
super.onDestroy()
printTaskInfo(this, "onDestroy")
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> onBackPressed()
}
return super.onOptionsItemSelected(item)
}
}

此处还需要另一个Kotlin文件

package com.lyf.launchmodektdemo

import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.util.Log
import androidx.appcompat.app.AppCompatActivity

fun printTaskInfo(activity: BaseActivity, methodName: String) {
    log("$methodName: ${activity.localClassName} taskId: ${activity.taskId} hashCode: ${activity.hashCode()}")
}

fun log(message: String, tag: String = "LaunchMode") {
    Log.i(tag, message)
}

fun dumpTaskAffinity(activity: BaseActivity) {
    val info = activity.packageManager.getActivityInfo(
        activity.componentName,
        PackageManager.GET_META_DATA
    )
    log("taskAffinity: ${info.taskAffinity}")
}

/**
 * @param T 目标 Activity
 */
inline fun <reified T : AppCompatActivity> Context.toActivity() {
    startActivity(Intent(this, T::class.java))
}

一、standard——标准模式(默认模式)

  这个模式是默认的启动模式,即标准模式,在不指定启动模式的前提下,系统默认使用该模式启动Activity,每次启动一个Activity都会重新创建一个新的实例,不管这个实例存不存在,这种模式下,谁启动了该模式的Activity,该Activity就属于启动它的Activity的任务栈。这个Activity它的onCreate(),onStart(),onResume()方法都会被调用。

配置形式:


<activity
android:name=".StandardActivity"
android:launchMode="standard" />

使用案例:

  StandardActivity

  对于standard模式,android:launchMode可以不进行声明,因为默认就是standard。 
  StandardActivity 的代码如下,入口Activity中有一个按钮进入该Activity,这个Activity中又有一个按钮启动StandardActivity。


package com.lyf.launchmodektdemo

import android.os.Bundle
import kotlinx.android.synthetic.main.activity_standard.*

class StandardActivity : BaseActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_standard)

btn_self.setOnClickListener {
toActivity<StandardActivity>()
}
}
}

  进入StandardActivity,然后再点击两次“启动自身”按钮。

输出的日志如下:

2020-04-29 16:07:32.235 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onCreate: MainActivity taskId: 40477 hashCode: 32430795
2020-04-29 16:07:32.236 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.launchmodektdemo
2020-04-29 16:07:32.259 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onStart: MainActivity taskId: 40477 hashCode: 32430795
2020-04-29 16:07:32.262 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onResume: MainActivity taskId: 40477 hashCode: 32430795

2020-04-29 16:07:34.490 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onPause: MainActivity taskId: 40477 hashCode: 32430795
2020-04-29 16:07:34.518 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onCreate: StandardActivity taskId: 40477 hashCode: 90465235
2020-04-29 16:07:34.518 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.launchmodektdemo
2020-04-29 16:07:34.527 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onStart: StandardActivity taskId: 40477 hashCode: 90465235
2020-04-29 16:07:34.532 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onResume: StandardActivity taskId: 40477 hashCode: 90465235
2020-04-29 16:07:34.867 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onSaveInstanceState: MainActivity taskId: 40477 hashCode: 32430795
2020-04-29 16:07:34.869 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onStop: MainActivity taskId: 40477 hashCode: 32430795

2020-04-29 16:07:35.423 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onPause: StandardActivity taskId: 40477 hashCode: 90465235
2020-04-29 16:07:35.448 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onCreate: StandardActivity taskId: 40477 hashCode: 139304006
2020-04-29 16:07:35.449 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.launchmodektdemo
2020-04-29 16:07:35.455 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onStart: StandardActivity taskId: 40477 hashCode: 139304006
2020-04-29 16:07:35.458 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onResume: StandardActivity taskId: 40477 hashCode: 139304006
2020-04-29 16:07:35.780 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onSaveInstanceState: StandardActivity taskId: 40477 hashCode: 90465235
2020-04-29 16:07:35.782 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onStop: StandardActivity taskId: 40477 hashCode: 90465235

2020-04-29 16:07:36.215 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onPause: StandardActivity taskId: 40477 hashCode: 139304006
2020-04-29 16:07:36.240 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onCreate: StandardActivity taskId: 40477 hashCode: 102119413
2020-04-29 16:07:36.241 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.launchmodektdemo
2020-04-29 16:07:36.246 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onStart: StandardActivity taskId: 40477 hashCode: 102119413
2020-04-29 16:07:36.249 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onResume: StandardActivity taskId: 40477 hashCode: 102119413
2020-04-29 16:07:36.576 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onSaveInstanceState: StandardActivity taskId: 40477 hashCode: 139304006
2020-04-29 16:07:36.578 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onStop: StandardActivity taskId: 40477 hashCode: 139304006

可以看到日志输出了三次StandardActivity的和一次MainActivity的,从MainActivity进入StandardActivity一次,后来我们又按了两次按钮,总共三次StandardActivity的日志,并且所属的任务栈的id都是40477,这也验证了谁启动了该模式的Activity,该Activity就属于启动它的Activity的任务栈这句话,因为启动StandardActivity的是MainActivity,而MainActivity的taskId是40477,因此启动的StandardActivity也应该属于id为40477的这个task,后续的两个StandardActivity是被StandardActivity这个对象启动的,因此也应该还是40477,所以taskId都是40477。并且每一个Activity的hashcode都是不一样的,说明他们是不同的实例,即“每次启动一个Activity都会重新创建一个新的实例”。

二、singleTop——Task栈顶单例模式(栈顶复用模式)

  此模式下,如果新的activity已经位于栈顶,那么这个activity不会被重新创建,同时他的onNewIntent方法会被调用,此时这个activity的onCreate(),onStart()方法没有回调,onResume()方法会被回调,所以这个activity没有发生改变,还是同一个activity。通过此方法的参数我们可以获取当前请求的信息。如果栈顶不存在该activity的实例,则情况与standard模式相同。

配置形式:


<activity
android:name=".SingleTopActivity"
android:launchMode="singleTop"
android:taskAffinity="com.lyf.test.singleTop" />

使用案例:

 SingleTopActivity

 



package com.lyf.launchmodektdemo

import android.os.Bundle
import kotlinx.android.synthetic.main.activity_single_top.*

class SingleTopActivity : BaseActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_single_top)

btn_self.setOnClickListener {
toActivity<SingleTopActivity>()
}

btn_other.setOnClickListener {
toActivity<OtherTopActivity>()
// toActivity<MainActivity>()
}
}
}

OtherTopActivity



package com.lyf.launchmodektdemo

import android.os.Bundle
import kotlinx.android.synthetic.main.activity_other_top.*

class OtherTopActivity : BaseActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_other_top)

btn_top.setOnClickListener {
toActivity<SingleTopActivity>()
}
}
}

1、和standard启动方式一样,先启动SingleTopActivity,然后点击两次“启动自身”按钮

  输出日志如下:

2020-04-29 16:10:38.177 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onCreate: MainActivity taskId: 40478 hashCode: 264932
2020-04-29 16:10:38.178 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.launchmodektdemo
2020-04-29 16:10:38.194 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onStart: MainActivity taskId: 40478 hashCode: 264932
2020-04-29 16:10:38.197 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onResume: MainActivity taskId: 40478 hashCode: 264932

2020-04-29 16:10:39.872 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onPause: MainActivity taskId: 40478 hashCode: 264932
2020-04-29 16:10:39.902 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onCreate: SingleTopActivity taskId: 40478 hashCode: 246478133
2020-04-29 16:10:39.903 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.launchmodektdemo
2020-04-29 16:10:39.916 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onStart: SingleTopActivity taskId: 40478 hashCode: 246478133
2020-04-29 16:10:39.920 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onResume: SingleTopActivity taskId: 40478 hashCode: 246478133
2020-04-29 16:10:40.261 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onSaveInstanceState: MainActivity taskId: 40478 hashCode: 264932
2020-04-29 16:10:40.263 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onStop: MainActivity taskId: 40478 hashCode: 264932

2020-04-29 16:10:42.664 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onPause: SingleTopActivity taskId: 40478 hashCode: 246478133
2020-04-29 16:10:42.666 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onNewIntent: SingleTopActivity taskId: 40478 hashCode: 246478133
2020-04-29 16:10:42.667 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.launchmodektdemo
2020-04-29 16:10:42.669 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onResume: SingleTopActivity taskId: 40478 hashCode: 246478133

2020-04-29 16:10:44.706 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onPause: SingleTopActivity taskId: 40478 hashCode: 246478133
2020-04-29 16:10:44.707 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onNewIntent: SingleTopActivity taskId: 40478 hashCode: 246478133
2020-04-29 16:10:44.709 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.launchmodektdemo
2020-04-29 16:10:44.712 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onResume: SingleTopActivity taskId: 40478 hashCode: 246478133

从日志可以看出,除了第一次进入SingleTopActivity这个Activity时,输出的是onCreate方法中的日志,后续的都是调用了onNewIntent方法,并没有回调onCreate、onStart方法,回调了onResume方法,并且三个日志的hashcode都是一样的,说明栈中只有一个实例。这是因为第一次进入的时候,栈中没有该实例,则创建,后续的两次发现栈顶有这个实例,则直接复用,并且调用onNewIntent方法。

那么假设栈中有该实例,但是该实例不在栈顶情况又如何呢?

我们先从MainActivity进入到SingleTopActivity,然后点击“启动另外一个activity”启动OtherTopActivity,再从OtherTopActivity调回SingleTopActivity,再从SingleTopActivity跳到SingleTopActivity。日志如下:

2020-04-29 16:12:26.281 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onCreate: MainActivity taskId: 40479 hashCode: 213102559
2020-04-29 16:12:26.282 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.launchmodektdemo
2020-04-29 16:12:26.295 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onStart: MainActivity taskId: 40479 hashCode: 213102559
2020-04-29 16:12:26.298 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onResume: MainActivity taskId: 40479 hashCode: 213102559

2020-04-29 16:12:28.257 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onPause: MainActivity taskId: 40479 hashCode: 213102559
2020-04-29 16:12:28.283 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onCreate: SingleTopActivity taskId: 40479 hashCode: 178327198
2020-04-29 16:12:28.284 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.launchmodektdemo
2020-04-29 16:12:28.292 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onStart: SingleTopActivity taskId: 40479 hashCode: 178327198
2020-04-29 16:12:28.296 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onResume: SingleTopActivity taskId: 40479 hashCode: 178327198
2020-04-29 16:12:28.627 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onSaveInstanceState: MainActivity taskId: 40479 hashCode: 213102559
2020-04-29 16:12:28.628 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onStop: MainActivity taskId: 40479 hashCode: 213102559

2020-04-29 16:12:30.413 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onPause: SingleTopActivity taskId: 40479 hashCode: 178327198
2020-04-29 16:12:30.441 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onCreate: OtherTopActivity taskId: 40479 hashCode: 135729268
2020-04-29 16:12:30.441 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.launchmodektdemo
2020-04-29 16:12:30.447 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onStart: OtherTopActivity taskId: 40479 hashCode: 135729268
2020-04-29 16:12:30.450 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onResume: OtherTopActivity taskId: 40479 hashCode: 135729268
2020-04-29 16:12:30.767 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onSaveInstanceState: SingleTopActivity taskId: 40479 hashCode: 178327198
2020-04-29 16:12:30.769 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onStop: SingleTopActivity taskId: 40479 hashCode: 178327198

2020-04-29 16:12:31.873 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onPause: OtherTopActivity taskId: 40479 hashCode: 135729268
2020-04-29 16:12:31.900 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onCreate: SingleTopActivity taskId: 40479 hashCode: 148854986
2020-04-29 16:12:31.900 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.launchmodektdemo
2020-04-29 16:12:31.909 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onStart: SingleTopActivity taskId: 40479 hashCode: 148854986
2020-04-29 16:12:31.912 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onResume: SingleTopActivity taskId: 40479 hashCode: 148854986
2020-04-29 16:12:32.244 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onSaveInstanceState: OtherTopActivity taskId: 40479 hashCode: 135729268
2020-04-29 16:12:32.246 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onStop: OtherTopActivity taskId: 40479 hashCode: 135729268

2020-04-29 16:12:35.347 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onPause: SingleTopActivity taskId: 40479 hashCode: 148854986
2020-04-29 16:12:35.348 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onNewIntent: SingleTopActivity taskId: 40479 hashCode: 148854986
2020-04-29 16:12:35.349 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.launchmodektdemo
2020-04-29 16:12:35.351 11953-11953/com.lyf.launchmodektdemo I/LaunchMode: onResume: SingleTopActivity taskId: 40479 hashCode: 148854986

我们看到从MainActivity进入到SingleTopActivity时,新建了一个SingleTopActivity对象,并且task id与MainActivity是一样的,然后从SingleTopActivity跳到OtherActivity时,新建了一个OtherActivity,此时task中存在三个Activity,从栈底到栈顶依次是MainActivity,SingleTopActivity,OtherActivity,此时如果再跳到SingleTopActivity,即使栈中已经有SingleTopActivity实例了,但是依然会创建一个新的SingleTopActivity实例,这一点从上面的日志的hashCode可以看出,此时栈顶是SingleTopActivity,如果再跳到SingleTopActivity,就会复用栈顶的SingleTopActivity,即会调用SingleTopActivity的onNewIntent方法。这就是上述日志的全过程。 

对以上内容进行总结 
       standard启动模式是默认的启动模式,每次启动一个Activity都会新建一个实例不管栈中是否已有该Activity的实例。 
singleTop模式分3种情况

  1. 当前栈中已有该Activity的实例并且该实例位于栈顶时,不会新建实例,而是复用栈顶的实例,并且会将Intent对象传入,回调onNewIntent方法
  2. 当前栈中已有该Activity的实例但是该实例不在栈顶时,其行为和standard启动模式一样,依然会创建一个新的实例
  3. 当前栈中不存在该Activity的实例时,其行为同standard启动模式

 standard和singleTop启动模式都是在原任务栈中新建Activity实例,不会启动新的Task,即使你指定了taskAffinity属性。

那么什么是taskAffinity属性呢,可以简单的理解为任务相关性。

  • 这个参数标识了一个Activity所需任务栈的名字,默认情况下,所有Activity所需的任务栈的名字为应用的包名
  • 我们可以单独指定每一个Activity的taskAffinity属性覆盖默认值
  • 一个任务的affinity决定于这个任务的根activity(root activity)的taskAffinity
  • 在概念上,具有相同的affinity的activity(即设置了相同taskAffinity属性的activity)属于同一个任务
  • 为一个activity的taskAffinity设置一个空字符串,表明这个activity不属于任何task

       很重要的一点taskAffinity属性不对standard和singleTop模式有任何影响,即时你指定了该属性为其他不同的值,这两种启动模式下不会创建新的task(如果不指定即默认值,即包名)

 指定方式如下:

<activity
    android:name=".SingleTopActivity"
    android:launchMode="singleTop"
    android:taskAffinity="com.lyf.test.singleTop" />

三、singleTask——Task栈内单例模式(栈内复用模式)

这个模式十分复杂,有各式各样的组合。在这个模式下,如果栈中存在这个Activity的实例就会复用这个Activity,不管它是否位于栈顶,复用时,会将它上面的Activity全部出栈,并且会回调该实例的onNewIntent方法。其实这个过程还存在一个任务栈的匹配,因为这个模式启动时,会在自己需要的任务栈中寻找实例,这个任务栈就是通过taskAffinity属性指定。如果这个任务栈不存在,则会创建这个任务栈。 

配置形式:

<activity
android:name=".SingleTaskActivity"
android:launchMode="singleTask" />

使用案例:

SingleTaskActivity


package com.lyf.launchmodektdemo

import android.os.Bundle
import kotlinx.android.synthetic.main.activity_single_task.*

class SingleTaskActivity : BaseActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_single_task)

btn_self.setOnClickListener {
toActivity<SingleTaskActivity>()
}

btn_other.setOnClickListener {
toActivity<OtherTask1Activity>()
// toActivity<MainActivity>()
}
}
}

OtherTaskActivity


package com.lyf.launchmodektdemo

import android.os.Bundle
import kotlinx.android.synthetic.main.activity_other_task.*

class OtherTaskActivity : BaseActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_other_task)

btn_task.setOnClickListener {
toActivity<SingleTaskActivity>()
}
}
}

现在我们先不指定任何taskAffinity属性,对它做类似singleTop的操作,即从入口MainActivity进入SingleTaskActivity,然后跳到OtherTaskActivity,再跳回到SingleTaskActivity,然后再启动一次SingleTaskActivity。看看整个过程的日志。

2020-04-29 16:25:02.985 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: onCreate: MainActivity taskId: 40489 hashCode: 184844997
2020-04-29 16:25:02.986 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.launchmodektdemo
2020-04-29 16:25:03.004 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: onStart: MainActivity taskId: 40489 hashCode: 184844997
2020-04-29 16:25:03.009 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: onResume: MainActivity taskId: 40489 hashCode: 184844997

2020-04-29 16:25:05.158 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: onPause: MainActivity taskId: 40489 hashCode: 184844997
2020-04-29 16:25:05.188 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: onCreate: SingleTaskActivity taskId: 40489 hashCode: 259974370
2020-04-29 16:25:05.188 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.launchmodektdemo
2020-04-29 16:25:05.200 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: onStart: SingleTaskActivity taskId: 40489 hashCode: 259974370
2020-04-29 16:25:05.204 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: onResume: SingleTaskActivity taskId: 40489 hashCode: 259974370
2020-04-29 16:25:05.550 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: onSaveInstanceState: MainActivity taskId: 40489 hashCode: 184844997
2020-04-29 16:25:05.551 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: onStop: MainActivity taskId: 40489 hashCode: 184844997

2020-04-29 16:25:06.739 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: onPause: SingleTaskActivity taskId: 40489 hashCode: 259974370
2020-04-29 16:25:06.770 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: onCreate: OtherTaskActivity taskId: 40489 hashCode: 191707012
2020-04-29 16:25:06.771 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.launchmodektdemo
2020-04-29 16:25:06.777 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: onStart: OtherTaskActivity taskId: 40489 hashCode: 191707012
2020-04-29 16:25:06.781 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: onResume: OtherTaskActivity taskId: 40489 hashCode: 191707012
2020-04-29 16:25:07.108 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: onSaveInstanceState: SingleTaskActivity taskId: 40489 hashCode: 259974370
2020-04-29 16:25:07.110 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: onStop: SingleTaskActivity taskId: 40489 hashCode: 259974370

2020-04-29 16:25:08.044 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: onPause: OtherTaskActivity taskId: 40489 hashCode: 191707012
2020-04-29 16:25:08.056 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: onNewIntent: SingleTaskActivity taskId: 40489 hashCode: 259974370
2020-04-29 16:25:08.057 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.launchmodektdemo
2020-04-29 16:25:08.058 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: onRestart: SingleTaskActivity taskId: 40489 hashCode: 259974370
2020-04-29 16:25:08.058 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: onStart: SingleTaskActivity taskId: 40489 hashCode: 259974370
2020-04-29 16:25:08.060 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: onResume: SingleTaskActivity taskId: 40489 hashCode: 259974370
2020-04-29 16:25:08.400 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: onStop: OtherTaskActivity taskId: 40489 hashCode: 191707012
2020-04-29 16:25:08.401 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: onDestroy: OtherTaskActivity taskId: 40489 hashCode: 191707012

2020-04-29 16:25:08.950 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: onPause: SingleTaskActivity taskId: 40489 hashCode: 259974370
2020-04-29 16:25:08.951 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: onNewIntent: SingleTaskActivity taskId: 40489 hashCode: 259974370
2020-04-29 16:25:08.953 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.launchmodektdemo
2020-04-29 16:25:08.955 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: onResume: SingleTaskActivity taskId: 40489 hashCode: 259974370

2020-04-29 16:25:10.130 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: onPause: SingleTaskActivity taskId: 40489 hashCode: 259974370
2020-04-29 16:25:10.132 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: onNewIntent: SingleTaskActivity taskId: 40489 hashCode: 259974370
2020-04-29 16:25:10.134 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.launchmodektdemo
2020-04-29 16:25:10.136 13514-13514/com.lyf.launchmodektdemo I/LaunchMode: onResume: SingleTaskActivity taskId: 40489 hashCode: 259974370

当我们从MainActiviyty进入到SingleTaskActivity,再进入到OtherTaskActivity后,此时栈中有3个Activity实例,并且SingleTaskActivity不在栈顶,而在OtherTaskActivity跳到SingleTaskActivity时,并没有创建一个新的SingleTaskActivity,而是复用了该实例,并且回调了onNewIntent方法。并且原来的OtherTaskActivity出栈了,具体见下面的信息,使用命令adb shell dumpsys activity activities可进行查看

TaskRecord{e5a85ca #40489 A=com.lyf.launchmodektdemo U=0 StackId=1 sz=2}
    Run #2: ActivityRecord{2a5292c u0 com.lyf.launchmodektdemo/.SingleTaskActivity t40489}
    Run #1: ActivityRecord{f9f926b u0 com.lyf.launchmodektdemo/.MainActivity t40489}

  可以看到当前栈中只有两个Activity,即原来栈中位于SingleTaskActivity 之上的Activity都出栈了。 


      我们看到使用singleTask启动模式启动一个Activity,它还是在原来的task中启动。其实是这样的,我们并没有指定taskAffinity属性,这说明和默认值一样,也就是包名,当MainActivity启动时创建的Task的名字就是包名,因为MainActivity也没有指定taskAffinity,而当我们启动SingleTaskActivity ,首先会寻找需要的任务栈是否存在,也就是taskAffinity指定的值,这里就是包名,发现存在,就不再创建新的task,而是直接使用。当该task中存在该Activity实例时就会复用该实例,这就是栈内复用模式。  

  这时候,如果我们指定SingleTaskActivity 的taskAffinity值。

<activity
            android:name=".SingleTaskActivity"
            android:launchMode="singleTask"
            android:taskAffinity="com.lyf.test.singleTask" />
  这时候,如果我们指定SingleTaskActivity 的taskAffinity值。
2020-04-29 16:49:33.424 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onRestart: MainActivity taskId: 40512 hashCode: 240024050
2020-04-29 16:49:33.429 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onStart: MainActivity taskId: 40512 hashCode: 240024050
2020-04-29 16:49:33.437 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onResume: MainActivity taskId: 40512 hashCode: 240024050

2020-04-29 16:49:36.714 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onPause: MainActivity taskId: 40512 hashCode: 240024050
2020-04-29 16:49:36.781 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onCreate: SingleTaskActivity taskId: 40515 hashCode: 60225666
2020-04-29 16:49:36.781 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.test.singleTask
2020-04-29 16:49:36.794 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onStart: SingleTaskActivity taskId: 40515 hashCode: 60225666
2020-04-29 16:49:36.798 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onResume: SingleTaskActivity taskId: 40515 hashCode: 60225666
2020-04-29 16:49:37.336 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onSaveInstanceState: MainActivity taskId: 40512 hashCode: 240024050
2020-04-29 16:49:37.337 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onStop: MainActivity taskId: 40512 hashCode: 240024050

2020-04-29 16:49:39.118 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onPause: SingleTaskActivity taskId: 40515 hashCode: 60225666
2020-04-29 16:49:39.147 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onCreate: OtherTaskActivity taskId: 40515 hashCode: 176277901
2020-04-29 16:49:39.148 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.launchmodektdemo
2020-04-29 16:49:39.155 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onStart: OtherTaskActivity taskId: 40515 hashCode: 176277901
2020-04-29 16:49:39.158 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onResume: OtherTaskActivity taskId: 40515 hashCode: 176277901
2020-04-29 16:49:39.479 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onSaveInstanceState: SingleTaskActivity taskId: 40515 hashCode: 60225666
2020-04-29 16:49:39.481 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onStop: SingleTaskActivity taskId: 40515 hashCode: 60225666

2020-04-29 16:49:42.322 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onPause: OtherTaskActivity taskId: 40515 hashCode: 176277901
2020-04-29 16:49:42.332 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onNewIntent: SingleTaskActivity taskId: 40515 hashCode: 60225666
2020-04-29 16:49:42.333 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.test.singleTask
2020-04-29 16:49:42.333 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onRestart: SingleTaskActivity taskId: 40515 hashCode: 60225666
2020-04-29 16:49:42.334 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onStart: SingleTaskActivity taskId: 40515 hashCode: 60225666
2020-04-29 16:49:42.335 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onResume: SingleTaskActivity taskId: 40515 hashCode: 60225666
2020-04-29 16:49:42.679 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onStop: OtherTaskActivity taskId: 40515 hashCode: 176277901
2020-04-29 16:49:42.680 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onDestroy: OtherTaskActivity taskId: 40515 hashCode: 176277901

2020-04-29 16:49:44.245 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onPause: SingleTaskActivity taskId: 40515 hashCode: 60225666
2020-04-29 16:49:44.245 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onNewIntent: SingleTaskActivity taskId: 40515 hashCode: 60225666
2020-04-29 16:49:44.246 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.test.singleTask
2020-04-29 16:49:44.249 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onResume: SingleTaskActivity taskId: 40515 hashCode: 60225666

我们看到SingleTaskActivity所属的任务栈的TaskId发生了变化,也就是说开启了一个新的Task,并且之后的OtherActivity也运行在了该Task上 。
打印出信息也证明了存在两个不同的Task:

TaskRecord{babe221 #40515 A=com.lyf.test.singleTask U=0 StackId=1 sz=1}
    Run #2: ActivityRecord{c1d7e91 u0 com.lyf.launchmodektdemo/.SingleTaskActivity t40515}
TaskRecord{eb83944 #40512 A=com.lyf.launchmodektdemo U=0 StackId=1 sz=1}
    Run #1: ActivityRecord{94299af u0 com.lyf.launchmodektdemo/.MainActivity t40512}

 如果我们指定SingleTaskActivity的taskAffinity属性与MainActivity一样,又会出现什么情况呢?

配置形式:

<activity
    android:name=".SingleTaskActivity"
    android:launchMode="singleTask"
    android:taskAffinity="com.lyf.test.launchmodedemo" />

没错,就是和他们什么都不指定是一样的。 
这时候,就有了下面的结论 
singleTask启动模式启动Activity时,首先会根据taskAffinity去寻找当前是否存在一个对应名字的任务栈

  • 如果不存在,则会创建一个新的Task,并创建新的Activity实例入栈到新创建的Task中去
  • 如果存在,则得到该任务栈,查找该任务栈中是否存在该Activity实例 
            如果存在该实例,则将它上面的Activity实例都出栈,然后回调启动的Activity实例的onNewIntent方法 
            如果不存在该实例,则新建Activity,并入栈

此外,我们可以将两个不同App中的Activity设置为相同的taskAffinity,这样虽然在不同的应用中,但是Activity会被分配到同一个Task中去。 

我们再创建另外一个应用,指定它的taskAffinity和之前的一样,都是com.lyf.test.singleTask

<activity
android:name=".OtherSingleTaskActivity"
android:launchMode="singleTask"
android:taskAffinity="com.lyf.test.singleTask" />

注意:新应用的activity也应设置为singleTask模式。否则效果是不一样的。

先启动一个应用,让他跳转到该Activity后,再按home键让该应用在后台运行,然后启动另一个应用再进入栈内单例Activity,看日志

2020-04-29 16:28:55.725 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onCreate: MainActivity taskId: 40496 hashCode: 223658940
2020-04-29 16:28:55.726 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.launchmodektdemo
2020-04-29 16:28:55.760 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onStart: MainActivity taskId: 40496 hashCode: 223658940
2020-04-29 16:28:55.766 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onResume: MainActivity taskId: 40496 hashCode: 223658940

2020-04-29 16:29:02.961 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onPause: MainActivity taskId: 40496 hashCode: 223658940
2020-04-29 16:29:03.025 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onCreate: SingleTaskActivity taskId: 40497 hashCode: 87000641
2020-04-29 16:29:03.025 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.test.singleTask
2020-04-29 16:29:03.036 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onStart: SingleTaskActivity taskId: 40497 hashCode: 87000641
2020-04-29 16:29:03.040 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onResume: SingleTaskActivity taskId: 40497 hashCode: 87000641
2020-04-29 16:29:03.596 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onSaveInstanceState: MainActivity taskId: 40496 hashCode: 223658940
2020-04-29 16:29:03.597 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onStop: MainActivity taskId: 40496 hashCode: 223658940
2020-04-29 16:29:27.895 14457-14457/com.lyf.singletaskdemo I/LaunchMode: *****onCreate()方法*****
2020-04-29 16:29:27.896 14457-14457/com.lyf.singletaskdemo I/LaunchMode: onCreate: MainActivity taskId: 40499 hashCode: 194327709
2020-04-29 16:29:27.896 14457-14457/com.lyf.singletaskdemo I/LaunchMode: taskAffinity: com.lyf.singletaskdemo
2020-04-29 16:29:27.904 14457-14457/com.lyf.singletaskdemo I/LaunchMode: *****onStart()方法*****
2020-04-29 16:29:27.908 14457-14457/com.lyf.singletaskdemo I/LaunchMode: *****onResume()方法*****

2020-04-29 16:29:30.703 14457-14457/com.lyf.singletaskdemo I/LaunchMode: *****onCreate()方法*****
2020-04-29 16:29:30.704 14457-14457/com.lyf.singletaskdemo I/LaunchMode: onCreate: SingleTaskActivity taskId: 40497 hashCode: 34523045
2020-04-29 16:29:30.704 14457-14457/com.lyf.singletaskdemo I/LaunchMode: taskAffinity: com.lyf.test.singleTask
2020-04-29 16:29:30.710 14457-14457/com.lyf.singletaskdemo I/LaunchMode: *****onStart()方法*****
2020-04-29 16:29:30.715 14457-14457/com.lyf.singletaskdemo I/LaunchMode: *****onResume()方法*****

我们看到,指定了相同的taskAffinity的SingleTaskActivity和OtherActivityActivity被启动到了同一个task中,taskId都为40497。

TaskRecord{70a40f7 #40497 A=com.lyf.test.singleTask U=0 StackId=1 sz=2}
    Run #4: ActivityRecord{e30ad3f u0 com.lyf.singletaskdemo/.SingleTaskActivity t40497}
TaskRecord{c17f593 #40499 A=com.lyf.singletaskdemo U=0 StackId=1 sz=1}
    Run #3: ActivityRecord{c7f6489 u0 com.lyf.singletaskdemo/.MainActivity t40499}
TaskRecord{70a40f7 #40497 A=com.lyf.test.singleTask U=0 StackId=1 sz=2}
    Run #2: ActivityRecord{d7c5801 u0 com.lyf.launchmodektdemo/.SingleTaskActivity t40497}
TaskRecord{703dc9 #40496 A=com.lyf.launchmodektdemo U=0 StackId=1 sz=1}
    Run #1: ActivityRecord{5f830e4 u0 com.lyf.launchmodektdemo/.MainActivity t40496}

 四、singleInstance——全局单例模式

 这种模式下的Activity会单独占用一个Task栈,具有全局唯一性,即整个系统中就这么一个实例,由于栈内复用的特性,后续的请求均不会创建新的Activity实例,除非这个特殊的任务栈被销毁了。以singleInstance模式启动的Activity在整个系统中是单例的,如果在启动这样的Activity时,已经存在了一个实例,那么会把它所在的任务调度到前台,重用这个实例。 

 配置形式:

<activity
            android:name=".SingleInstanceActivity"
            android:launchMode="singleInstance">
            <intent-filter>
                <action android:name="com.lyf.test.singleinstancedemo" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

使用案例:


package com.lyf.launchmodektdemo

import android.os.Bundle
import kotlinx.android.synthetic.main.activity_single_instance.*

class SingleInstanceActivity : BaseActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_single_instance)

btn_self.setOnClickListener {
toActivity<SingleInstanceActivity>()
}

btn_instance.setOnClickListener {
toActivity<OtherInstanceActivity>()
// toActivity<MainActivity>()
}
}
}

现在我们先不指定任何taskAffinity属性,对它做类似singleTask的操作,即从入口MainActivity进入SingleInstanceActivity,然后跳到OtherInstanceActivity,再跳回到SingleInstanceActivity,然后再启动一次SingleInstanceActivity。看看整个过程的日志。

2020-04-29 16:33:31.542 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onCreate: MainActivity taskId: 40501 hashCode: 252960824
2020-04-29 16:33:31.542 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.launchmodektdemo
2020-04-29 16:33:31.560 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onStart: MainActivity taskId: 40501 hashCode: 252960824
2020-04-29 16:33:31.564 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onResume: MainActivity taskId: 40501 hashCode: 252960824

2020-04-29 16:33:33.366 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onPause: MainActivity taskId: 40501 hashCode: 252960824
2020-04-29 16:33:33.417 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onCreate: SingleInstanceActivity taskId: 40502 hashCode: 196024178
2020-04-29 16:33:33.417 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.launchmodektdemo
2020-04-29 16:33:33.427 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onStart: SingleInstanceActivity taskId: 40502 hashCode: 196024178
2020-04-29 16:33:33.431 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onResume: SingleInstanceActivity taskId: 40502 hashCode: 196024178
2020-04-29 16:33:33.989 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onSaveInstanceState: MainActivity taskId: 40501 hashCode: 252960824
2020-04-29 16:33:33.990 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onStop: MainActivity taskId: 40501 hashCode: 252960824

2020-04-29 16:33:36.899 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onPause: SingleInstanceActivity taskId: 40502 hashCode: 196024178
2020-04-29 16:33:36.939 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onCreate: OtherInstanceActivity taskId: 40501 hashCode: 59304459
2020-04-29 16:33:36.939 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.launchmodektdemo
2020-04-29 16:33:36.945 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onStart: OtherInstanceActivity taskId: 40501 hashCode: 59304459
2020-04-29 16:33:36.948 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onResume: OtherInstanceActivity taskId: 40501 hashCode: 59304459
2020-04-29 16:33:37.599 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onSaveInstanceState: SingleInstanceActivity taskId: 40502 hashCode: 196024178
2020-04-29 16:33:37.601 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onStop: SingleInstanceActivity taskId: 40502 hashCode: 196024178

2020-04-29 16:33:39.966 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onPause: OtherInstanceActivity taskId: 40501 hashCode: 59304459
2020-04-29 16:33:39.991 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onNewIntent: SingleInstanceActivity taskId: 40502 hashCode: 196024178
2020-04-29 16:33:39.991 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.launchmodektdemo
2020-04-29 16:33:39.992 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onRestart: SingleInstanceActivity taskId: 40502 hashCode: 196024178
2020-04-29 16:33:39.993 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onStart: SingleInstanceActivity taskId: 40502 hashCode: 196024178
2020-04-29 16:33:39.995 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onResume: SingleInstanceActivity taskId: 40502 hashCode: 196024178
2020-04-29 16:33:40.620 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onSaveInstanceState: OtherInstanceActivity taskId: 40501 hashCode: 59304459
2020-04-29 16:33:40.622 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onStop: OtherInstanceActivity taskId: 40501 hashCode: 59304459

2020-04-29 16:33:43.046 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onPause: SingleInstanceActivity taskId: 40502 hashCode: 196024178
2020-04-29 16:33:43.046 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onNewIntent: SingleInstanceActivity taskId: 40502 hashCode: 196024178
2020-04-29 16:33:43.047 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.launchmodektdemo
2020-04-29 16:33:43.049 14220-14220/com.lyf.launchmodektdemo I/LaunchMode: onResume: SingleInstanceActivity taskId: 40502 hashCode: 196024178

当我们从MainActiviyty进入到SingleInstanceActivity,再进入到OtherInstanceActivity后,此时栈中有3个Activity实例,SingleInstanceActivity单独在一个Task中,而从OtherInstanceActivity跳到SingleInstanceActivity时,并没有创建一个新的SingleInstanceActivity,而是复用了该实例,并且回调了onNewIntent方法。并且原来的OtherInstanceActivity没有出栈,具体见下面的信息,使用命令adb shell dumpsys activity activities可进行查看

TaskRecord{c2d2bf5 #40502 A=com.lyf.launchmodektdemo U=0 StackId=1 sz=1}
    Run #3: ActivityRecord{a002f8d u0 com.lyf.launchmodektdemo/.SingleInstanceActivity t40502}
TaskRecord{9de7ffb #40501 A=com.lyf.launchmodektdemo U=0 StackId=1 sz=2}
    Run #2: ActivityRecord{c4a3bae u0 com.lyf.launchmodektdemo/.OtherInstanceActivity t40501}
    Run #1: ActivityRecord{28990d4 u0 com.lyf.launchmodektdemo/.MainActivity t40501}

可以看到当前栈中只有三个Activity。 
       我们看到使用singleInstance启动模式启动一个Activity,它创建了一个新的task。

这时候,如果我们指定SingleInstanceActivity 的taskAffinity值。

<activity
            android:name=".SingleInstanceActivity"
            android:launchMode="singleInstance"
            android:taskAffinity="com.lyf.test.singleInstance">
            <intent-filter>
                <action android:name="com.lyf.test.singleinstancedemo" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

执行上述同样的操作:

2020-04-29 16:36:52.237 15405-15405/com.lyf.launchmodektdemo I/LaunchMode: onCreate: MainActivity taskId: 40506 hashCode: 184844997
2020-04-29 16:36:52.238 15405-15405/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.launchmodektdemo
2020-04-29 16:36:52.257 15405-15405/com.lyf.launchmodektdemo I/LaunchMode: onStart: MainActivity taskId: 40506 hashCode: 184844997
2020-04-29 16:36:52.261 15405-15405/com.lyf.launchmodektdemo I/LaunchMode: onResume: MainActivity taskId: 40506 hashCode: 184844997

2020-04-29 16:36:54.081 15405-15405/com.lyf.launchmodektdemo I/LaunchMode: onPause: MainActivity taskId: 40506 hashCode: 184844997
2020-04-29 16:36:54.146 15405-15405/com.lyf.launchmodektdemo I/LaunchMode: onCreate: SingleInstanceActivity taskId: 40507 hashCode: 150301101
2020-04-29 16:36:54.147 15405-15405/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.test.singleinstancedemo
2020-04-29 16:36:54.160 15405-15405/com.lyf.launchmodektdemo I/LaunchMode: onStart: SingleInstanceActivity taskId: 40507 hashCode: 150301101
2020-04-29 16:36:54.165 15405-15405/com.lyf.launchmodektdemo I/LaunchMode: onResume: SingleInstanceActivity taskId: 40507 hashCode: 150301101
2020-04-29 16:36:54.707 15405-15405/com.lyf.launchmodektdemo I/LaunchMode: onSaveInstanceState: MainActivity taskId: 40506 hashCode: 184844997
2020-04-29 16:36:54.708 15405-15405/com.lyf.launchmodektdemo I/LaunchMode: onStop: MainActivity taskId: 40506 hashCode: 184844997

2020-04-29 16:36:56.430 15405-15405/com.lyf.launchmodektdemo I/LaunchMode: onPause: SingleInstanceActivity taskId: 40507 hashCode: 150301101
2020-04-29 16:36:56.480 15405-15405/com.lyf.launchmodektdemo I/LaunchMode: onCreate: OtherInstanceActivity taskId: 40506 hashCode: 114298043
2020-04-29 16:36:56.481 15405-15405/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.launchmodektdemo
2020-04-29 16:36:56.488 15405-15405/com.lyf.launchmodektdemo I/LaunchMode: onStart: OtherInstanceActivity taskId: 40506 hashCode: 114298043
2020-04-29 16:36:56.492 15405-15405/com.lyf.launchmodektdemo I/LaunchMode: onResume: OtherInstanceActivity taskId: 40506 hashCode: 114298043
2020-04-29 16:36:57.137 15405-15405/com.lyf.launchmodektdemo I/LaunchMode: onSaveInstanceState: SingleInstanceActivity taskId: 40507 hashCode: 150301101
2020-04-29 16:36:57.140 15405-15405/com.lyf.launchmodektdemo I/LaunchMode: onStop: SingleInstanceActivity taskId: 40507 hashCode: 150301101

2020-04-29 16:36:59.056 15405-15405/com.lyf.launchmodektdemo I/LaunchMode: onPause: OtherInstanceActivity taskId: 40506 hashCode: 114298043
2020-04-29 16:36:59.080 15405-15405/com.lyf.launchmodektdemo I/LaunchMode: onNewIntent: SingleInstanceActivity taskId: 40507 hashCode: 150301101
2020-04-29 16:36:59.081 15405-15405/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.test.singleinstancedemo
2020-04-29 16:36:59.081 15405-15405/com.lyf.launchmodektdemo I/LaunchMode: onRestart: SingleInstanceActivity taskId: 40507 hashCode: 150301101
2020-04-29 16:36:59.082 15405-15405/com.lyf.launchmodektdemo I/LaunchMode: onStart: SingleInstanceActivity taskId: 40507 hashCode: 150301101
2020-04-29 16:36:59.083 15405-15405/com.lyf.launchmodektdemo I/LaunchMode: onResume: SingleInstanceActivity taskId: 40507 hashCode: 150301101
2020-04-29 16:36:59.706 15405-15405/com.lyf.launchmodektdemo I/LaunchMode: onSaveInstanceState: OtherInstanceActivity taskId: 40506 hashCode: 114298043
2020-04-29 16:36:59.709 15405-15405/com.lyf.launchmodektdemo I/LaunchMode: onStop: OtherInstanceActivity taskId: 40506 hashCode: 114298043

2020-04-29 16:37:01.231 15405-15405/com.lyf.launchmodektdemo I/LaunchMode: onPause: SingleInstanceActivity taskId: 40507 hashCode: 150301101
2020-04-29 16:37:01.232 15405-15405/com.lyf.launchmodektdemo I/LaunchMode: onNewIntent: SingleInstanceActivity taskId: 40507 hashCode: 150301101
2020-04-29 16:37:01.234 15405-15405/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.test.singleinstancedemo
2020-04-29 16:37:01.238 15405-15405/com.lyf.launchmodektdemo I/LaunchMode: onResume: SingleInstanceActivity taskId: 40507 hashCode: 150301101
TaskRecord{ec31552 #40507 A=com.lyf.test.singleinstancedemo U=0 StackId=1 sz=1}
    Run #3: ActivityRecord{68ce1ba u0 com.lyf.launchmodektdemo/.SingleInstanceActivity t40507}
TaskRecord{3a472d9 #40506 A=com.lyf.launchmodektdemo U=0 StackId=1 sz=2}
    Run #2: ActivityRecord{b6d1c71 u0 com.lyf.launchmodektdemo/.OtherInstanceActivity t40506}
    Run #1: ActivityRecord{fd90bd5 u0 com.lyf.launchmodektdemo/.MainActivity t40506}

除了SingleInstanceActivity的taskAffinity变化之后,其他的结果与不指定taskAffinity是一样的。singleInstance的优先级大于taskAffinity,所以同时指定它们的时候也会按照singleInstance的设置得到对应的结果。

使用下面的方式分别在两个应用中启动它

Intent singleInstanceIntent = new Intent();
singleInstanceIntent.setAction("com.lyf.test.singleinstancedemo");
startActivity(singleInstanceIntent);

操作和上一个(使用两个app操作)一样,日志如下:

第一个应用启动,并跳转到singleInstance模式的Activity

2020-04-29 16:39:39.628 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onCreate: MainActivity taskId: 40512 hashCode: 240024050
2020-04-29 16:39:39.629 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.launchmodektdemo
2020-04-29 16:39:39.651 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onStart: MainActivity taskId: 40512 hashCode: 240024050
2020-04-29 16:39:39.655 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onResume: MainActivity taskId: 40512 hashCode: 240024050

2020-04-29 16:39:41.507 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onPause: MainActivity taskId: 40512 hashCode: 240024050
2020-04-29 16:39:41.556 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onCreate: SingleInstanceActivity taskId: 40513 hashCode: 240431118
2020-04-29 16:39:41.557 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.test.singleinstancedemo
2020-04-29 16:39:41.566 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onStart: SingleInstanceActivity taskId: 40513 hashCode: 240431118
2020-04-29 16:39:41.569 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onResume: SingleInstanceActivity taskId: 40513 hashCode: 240431118
2020-04-29 16:39:42.129 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onSaveInstanceState: MainActivity taskId: 40512 hashCode: 240024050
2020-04-29 16:39:42.131 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onStop: MainActivity taskId: 40512 hashCode: 240024050

第二个应用启动,尚未跳转

2020-04-29 16:40:19.340 16264-16264/com.lyf.singleinstancedemo I/LaunchMode: *****onCreate()方法*****
2020-04-29 16:40:19.341 16264-16264/com.lyf.singleinstancedemo I/LaunchMode: onCreate: MainActivity taskId: 40514 hashCode: 153400740
2020-04-29 16:40:19.341 16264-16264/com.lyf.singleinstancedemo I/LaunchMode: taskAffinity: com.lyf.singleinstancedemo
2020-04-29 16:40:19.355 16264-16264/com.lyf.singleinstancedemo I/LaunchMode: *****onStart()方法*****
2020-04-29 16:40:19.359 16264-16264/com.lyf.singleinstancedemo I/LaunchMode: *****onResume()方法*****

第二个应用启动,并跳转到singleInstance模式的Activity

2020-04-29 16:39:39.628 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onCreate: MainActivity taskId: 40512 hashCode: 240024050
2020-04-29 16:39:39.629 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.launchmodektdemo
2020-04-29 16:39:39.651 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onStart: MainActivity taskId: 40512 hashCode: 240024050
2020-04-29 16:39:39.655 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onResume: MainActivity taskId: 40512 hashCode: 240024050

2020-04-29 16:39:41.507 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onPause: MainActivity taskId: 40512 hashCode: 240024050
2020-04-29 16:39:41.556 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onCreate: SingleInstanceActivity taskId: 40513 hashCode: 240431118
2020-04-29 16:39:41.557 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.test.singleinstancedemo
2020-04-29 16:39:41.566 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onStart: SingleInstanceActivity taskId: 40513 hashCode: 240431118
2020-04-29 16:39:41.569 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onResume: SingleInstanceActivity taskId: 40513 hashCode: 240431118
2020-04-29 16:39:42.129 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onSaveInstanceState: MainActivity taskId: 40512 hashCode: 240024050
2020-04-29 16:39:42.131 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onStop: MainActivity taskId: 40512 hashCode: 240024050

2020-04-29 16:40:16.810 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onPause: SingleInstanceActivity taskId: 40513 hashCode: 240431118
2020-04-29 16:40:16.819 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onSaveInstanceState: SingleInstanceActivity taskId: 40513 hashCode: 240431118
2020-04-29 16:40:16.823 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onStop: SingleInstanceActivity taskId: 40513 hashCode: 240431118
2020-04-29 16:40:31.888 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onNewIntent: SingleInstanceActivity taskId: 40513 hashCode: 240431118
2020-04-29 16:40:31.889 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.test.singleinstancedemo
2020-04-29 16:40:31.892 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onRestart: SingleInstanceActivity taskId: 40513 hashCode: 240431118
2020-04-29 16:40:31.893 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onStart: SingleInstanceActivity taskId: 40513 hashCode: 240431118
2020-04-29 16:40:31.897 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onResume: SingleInstanceActivity taskId: 40513 hashCode: 240431118

我们看到,第一次应用启动SingleInstanceActivity时,由于系统中不存在该实例,所以新建了一个Task,按home键后,使用另一个App进入该Activity,由于系统中已经存在了一个实例,不会再创建新的Task,直接复用该实例,并且回调onNewIntent方法。可以从他们的hashcode中可以看出这是同一个实例。因此我们可以理解为:SingleInstance模式启动的Activity在系统中具有全局唯一性。

TaskRecord{508550a #40513 A=com.lyf.test.singleinstancedemo U=0 StackId=1 sz=1}
    Run #3: ActivityRecord{82b4336 u0 com.lyf.launchmodektdemo/.SingleInstanceActivity t40513}
TaskRecord{a3d9ff1 #40514 A=com.lyf.singleinstancedemo U=0 StackId=1 sz=1}
    Run #2: ActivityRecord{80e980 u0 com.lyf.singleinstancedemo/.MainActivity t40514}
TaskRecord{eb83944 #40512 A=com.lyf.launchmodektdemo U=0 StackId=1 sz=1}
    Run #1: ActivityRecord{94299af u0 com.lyf.launchmodektdemo/.MainActivity t40512}

git源码:https://github.com/First-Time/LaunchModeKTDemo.git

原文地址:https://www.cnblogs.com/diyishijian/p/7705588.html