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

Activity四大启动模式的更多相关文章

  1. 彻底弄懂Activity四大启动模式

    最近有几位朋友给我留言,让我谈一下对Activity启动模式的理解.我觉得对某个知识点的理解必须要动手操作才能印象深刻,所以今天写一篇博文,结合案例理解Activity启动模式.由于之前看过" ...

  2. Android中Activity的四大启动模式实验简述

    作为Android四大组件之一,Activity可以说是最基本也是最常见的组件,它提供了一个显示界面,从而实现与用户的交互,作为初学者,必须熟练掌握.今天我们就来通过实验演示,来帮助大家理解Activ ...

  3. Activity LauchMode启动模式(转载)

    转载于:http://www.cnblogs.com/plokmju/p/android_ActivityLauncherMode.html 在一个Android应用中,不可避免的会包含多个Activ ...

  4. Android开发艺术2之Activity的启动模式

    Activity是Android的四大组件之一,他的重要性毋庸置疑,对于这么重要的一个组件,我们首先要知道这些都是由系统进行管理和回调的,要理解Activity的启动模式,我们首先来了解一下Andro ...

  5. Activity的启动模式--总结

    3. Activity的任务栈Task以及启动模式与Intent的Flag详解? 2,Activity次级页面和主页间来回跳转,防止重复创建Activity实例 1, activity的启动模式: / ...

  6. 关于activity的启动模式

    在Android中每个界面都是一个Activity ,界面的切换实际上是对不同Activity实例化的过程.而启动模式就决定Activity启动运行方式. 1.设置方式它是在主配置文件中,Activi ...

  7. 无废话Android之activity的生命周期、activity的启动模式、activity横竖屏切换的生命周期、开启新的activity获取他的返回值、利用广播实现ip拨号、短信接收广播、短信监听器(6)

    1.activity的生命周期 这七个方法定义了Activity的完整生命周期.实现这些方法可以帮助我们监视其中的三个嵌套生命周期循环: (1)Activity的完整生命周期 自第一次调用onCrea ...

  8. android Activity的启动模式与flag的见解

    最近做一个安卓项目,想要实现的效果就是:当打开一个按钮的时候,启动了一个A功能,当用户返回到桌面再继续进去的时候,不过之前在哪个Activity,都会先跳转到A功能的那个界面,当用户点击返回的时候,再 ...

  9. android Activity的启动模式

    Android中Activity启动模式详解   在Android中每个界面都是一个Activity,切换界面操作其实是多个不同Activity之间的实例化操作.在Android中Activity的启 ...

随机推荐

  1. python advanced programming (Ⅲ)

    IO编程 IO在计算机中指Input/Output.由于程序和运行时数据是在内存中驻留,由CPU来执行,涉及到数据交换的地方,通常是磁盘.网络等,就需要IO接口. IO编程中,Stream(流)是一个 ...

  2. leetcode - [7]Binary Tree Preorder Traversal

    Given a binary tree, return the preorder traversal of its nodes' values. For example:Given binary tr ...

  3. noip第13课作业

    1.    排身高 [问题描述] 鹏鹏的班上一共有 n 个学生.刚好每个同学的身高互不相同.鹏鹏想知道,所有同学中身高第二高的是谁. 输入格式:输入共两行,第一行有一个整数 n(2≤n≤100),表示 ...

  4. [ 9.9 ]CF每日一题系列—— 259A黑白棋盘检查问题

    http://codeforces.com/problemset/problem/259/A PS9.8日做了但是忘了发博客,所以坚持3天了呦~ 终于读懂了这个题了,心累 Describe: 给你8 ...

  5. Python 中的深拷贝和浅拷贝

    一.浅拷贝python中 对象赋值时 默认是浅拷贝,满足如下规律:1. 对于 不可变对象(字符串,元组 等),赋值 实际上是创建一个新的对象:例如: >>> person=['nam ...

  6. Winform 自定义窗体皮肤组件

    分享一个很久之前写的一个Winform换肤组件. 主要利用CBT钩子,NativeWindow来实现.可实现动态换皮肤插件修改窗体显示外观. 我们先定义一个自定义组件 using Skin; usin ...

  7. C#序列化与反序列化以及深拷贝浅拷贝

    基于二进制数据流的序列化和反序列化 /// <summary> /// 序列化 /// </summary> /// <typeparam name="T&qu ...

  8. asp.net mvc+httpclient+asp.net mvc api入门篇

    第一步:创建一个ASP.NET MVC API项目 第二步:在api项目里面创建一个类 public class Student { public int Id { get; set; } publi ...

  9. 【BZOJ4755】 [Jsoi2016]扭动的回文串

    BZOJ4755 [Jsoi2016]扭动的回文串 Solution 考虑对于他给出的 A中的一个回文串: B中的一个回文串: 或者某一个回文的扭动字符串S(i,j,k) 这样子几个限制,我们1,2就 ...

  10. 常用Yum镜像源

    163网易的yum源 wget http://mirrors.163.com/.help/CentOS6-Base-163.repo sohu的yum源 wget http://mirrors.soh ...