ctivity的四种启动模式:

standard、singleTop、singleTask、singleInstance

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

  1. package com.lyf.launchmodektdemo
  2.  
  3. import android.content.Intent
    import android.os.Bundle
    import android.view.MenuItem
    import androidx.appcompat.app.ActionBar
    import androidx.appcompat.app.AppCompatActivity
  4.  
  5. open class BaseActivity : AppCompatActivity() {
    lateinit var actionBar: ActionBar
  6.  
  7. override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
  8.  
  9. actionBar = supportActionBar!!
    actionBar?.setDisplayHomeAsUpEnabled(true)
  10.  
  11. printTaskInfo(this, "onCreate")
    dumpTaskAffinity(this)
    }
  12.  
  13. override fun onNewIntent(intent: Intent?) {
    super.onNewIntent(intent)
    printTaskInfo(this, "onNewIntent")
    dumpTaskAffinity(this)
    }
  14.  
  15. override fun onRestart() {
    super.onRestart()
    printTaskInfo(this, "onRestart")
    }
  16.  
  17. override fun onStart() {
    super.onStart()
    printTaskInfo(this, "onStart")
    }
  18.  
  19. override fun onResume() {
    super.onResume()
    printTaskInfo(this, "onResume")
    }
  20.  
  21. override fun onPause() {
    super.onPause()
    printTaskInfo(this, "onPause")
    }
  22.  
  23. override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
    printTaskInfo(this, "onSaveInstanceState")
    }
  24.  
  25. override fun onStop() {
    super.onStop()
    printTaskInfo(this, "onStop")
    }
  26.  
  27. override fun onDestroy() {
    super.onDestroy()
    printTaskInfo(this, "onDestroy")
    }
  28.  
  29. override fun onOptionsItemSelected(item: MenuItem): Boolean {
    when (item.itemId) {
    android.R.id.home -> onBackPressed()
    }
    return super.onOptionsItemSelected(item)
    }
    }

此处还需要另一个Kotlin文件

  1. package com.lyf.launchmodektdemo
  2.  
  3. import android.content.Context
  4. import android.content.Intent
  5. import android.content.pm.PackageManager
  6. import android.util.Log
  7. import androidx.appcompat.app.AppCompatActivity
  8.  
  9. fun printTaskInfo(activity: BaseActivity, methodName: String) {
  10. log("$methodName: ${activity.localClassName} taskId: ${activity.taskId} hashCode: ${activity.hashCode()}")
  11. }
  12.  
  13. fun log(message: String, tag: String = "LaunchMode") {
  14. Log.i(tag, message)
  15. }
  16.  
  17. fun dumpTaskAffinity(activity: BaseActivity) {
  18. val info = activity.packageManager.getActivityInfo(
  19. activity.componentName,
  20. PackageManager.GET_META_DATA
  21. )
  22. log("taskAffinity: ${info.taskAffinity}")
  23. }
  24.  
  25. /**
  26. * @param T 目标 Activity
  27. */
  28. inline fun <reified T : AppCompatActivity> Context.toActivity() {
  29. startActivity(Intent(this, T::class.java))
  30. }

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

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

配置形式:

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

使用案例:

  StandardActivity

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

  1.  
  1. package com.lyf.launchmodektdemo
  2.  
  3. import android.os.Bundle
    import kotlinx.android.synthetic.main.activity_standard.*
  4.  
  5. class StandardActivity : BaseActivity() {
  6.  
  7. override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_standard)
  8.  
  9. btn_self.setOnClickListener {
    toActivity<StandardActivity>()
    }
    }
    }

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

输出的日志如下:

  1. 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
  2.  
  3. 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
  4.  
  5. 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
  6.  
  7. 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模式相同。

配置形式:

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

使用案例:

SingleTopActivity

 

  1.  
  1.  
  1. package com.lyf.launchmodektdemo
  2.  
  3. import android.os.Bundle
    import kotlinx.android.synthetic.main.activity_single_top.*
  4.  
  5. class SingleTopActivity : BaseActivity() {
  6.  
  7. override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_single_top)
  8.  
  9. btn_self.setOnClickListener {
    toActivity<SingleTopActivity>()
    }
  10.  
  11. btn_other.setOnClickListener {
    toActivity<OtherTopActivity>()
    // toActivity<MainActivity>()
    }
    }
    }

OtherTopActivity

  1.  
  1.  
  1. package com.lyf.launchmodektdemo
  2.  
  3. import android.os.Bundle
    import kotlinx.android.synthetic.main.activity_other_top.*
  4.  
  5. class OtherTopActivity : BaseActivity() {
  6.  
  7. override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_other_top)
  8.  
  9. btn_top.setOnClickListener {
    toActivity<SingleTopActivity>()
    }
    }
    }

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

  输出日志如下:

  1. 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
  2.  
  3. 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
  4.  
  5. 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
  6.  
  7. 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。日志如下:

  1. 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
  2.  
  3. 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
  4.  
  5. 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
  6.  
  7. 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
  8.  
  9. 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(如果不指定即默认值,即包名)

指定方式如下:

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

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

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

配置形式:

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

使用案例:

SingleTaskActivity

  1.  
  1. package com.lyf.launchmodektdemo
  2.  
  3. import android.os.Bundle
    import kotlinx.android.synthetic.main.activity_single_task.*
  4.  
  5. class SingleTaskActivity : BaseActivity() {
  6.  
  7. override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_single_task)
  8.  
  9. btn_self.setOnClickListener {
    toActivity<SingleTaskActivity>()
    }
  10.  
  11. btn_other.setOnClickListener {
    toActivity<OtherTask1Activity>()
    // toActivity<MainActivity>()
    }
    }
    }

OtherTaskActivity

  1.  
  1. package com.lyf.launchmodektdemo
  2.  
  3. import android.os.Bundle
    import kotlinx.android.synthetic.main.activity_other_task.*
  4.  
  5. class OtherTaskActivity : BaseActivity() {
  6.  
  7. override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_other_task)
  8.  
  9. btn_task.setOnClickListener {
    toActivity<SingleTaskActivity>()
    }
    }
    }

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

  1. 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
  2.  
  3. 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
  4.  
  5. 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
  6.  
  7. 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
  8.  
  9. 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
  10.  
  11. 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可进行查看

  1. 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值。

  1. <activity
  2. android:name=".SingleTaskActivity"
  3. android:launchMode="singleTask"
  4. android:taskAffinity="com.lyf.test.singleTask" />
  1.   这时候,如果我们指定SingleTaskActivity taskAffinity值。
  1. 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
  2.  
  3. 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
  4.  
  5. 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
  6.  
  7. 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
  8.  
  9. 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:

  1. 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一样,又会出现什么情况呢?

配置形式:

  1. <activity
  2. android:name=".SingleTaskActivity"
  3. android:launchMode="singleTask"
  4. 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

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

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

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

  1. 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
  2.  
  3. 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
  1. 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()方法*****
  2.  
  3. 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。

  1. 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时,已经存在了一个实例,那么会把它所在的任务调度到前台,重用这个实例。

 配置形式:

  1. <activity
  2. android:name=".SingleInstanceActivity"
  3. android:launchMode="singleInstance">
  4. <intent-filter>
  5. <action android:name="com.lyf.test.singleinstancedemo" />
  6.  
  7. <category android:name="android.intent.category.DEFAULT" />
  8. </intent-filter>
  9. </activity>

使用案例:

  1.  
  1. package com.lyf.launchmodektdemo
  2.  
  3. import android.os.Bundle
    import kotlinx.android.synthetic.main.activity_single_instance.*
  4.  
  5. class SingleInstanceActivity : BaseActivity() {
  6.  
  7. override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_single_instance)
  8.  
  9. btn_self.setOnClickListener {
    toActivity<SingleInstanceActivity>()
    }
  10.  
  11. btn_instance.setOnClickListener {
    toActivity<OtherInstanceActivity>()
    // toActivity<MainActivity>()
    }
    }
    }

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

  1. 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
  2.  
  3. 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
  4.  
  5. 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
  6.  
  7. 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
  8.  
  9. 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可进行查看

  1. 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值。

  1. <activity
  2. android:name=".SingleInstanceActivity"
  3. android:launchMode="singleInstance"
  4. android:taskAffinity="com.lyf.test.singleInstance">
  5. <intent-filter>
  6. <action android:name="com.lyf.test.singleinstancedemo" />
  7.  
  8. <category android:name="android.intent.category.DEFAULT" />
  9. </intent-filter>
  10. </activity>

执行上述同样的操作:

  1. 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
  2.  
  3. 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
  4.  
  5. 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
  6.  
  7. 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
  8.  
  9. 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
  1. 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的设置得到对应的结果。

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

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

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

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

  1. 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
  2.  
  3. 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

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

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

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

  1. 2020-04-29 16:39:39.628 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onCreate: MainActivity taskId: 40512 hashCode: 240024050
  2. 2020-04-29 16:39:39.629 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.launchmodektdemo
  3. 2020-04-29 16:39:39.651 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onStart: MainActivity taskId: 40512 hashCode: 240024050
  4. 2020-04-29 16:39:39.655 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onResume: MainActivity taskId: 40512 hashCode: 240024050
  5.  
  6. 2020-04-29 16:39:41.507 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onPause: MainActivity taskId: 40512 hashCode: 240024050
  7. 2020-04-29 16:39:41.556 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onCreate: SingleInstanceActivity taskId: 40513 hashCode: 240431118
  8. 2020-04-29 16:39:41.557 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.test.singleinstancedemo
  9. 2020-04-29 16:39:41.566 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onStart: SingleInstanceActivity taskId: 40513 hashCode: 240431118
  10. 2020-04-29 16:39:41.569 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onResume: SingleInstanceActivity taskId: 40513 hashCode: 240431118
  11. 2020-04-29 16:39:42.129 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onSaveInstanceState: MainActivity taskId: 40512 hashCode: 240024050
  12. 2020-04-29 16:39:42.131 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onStop: MainActivity taskId: 40512 hashCode: 240024050
  13.  
  14. 2020-04-29 16:40:16.810 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onPause: SingleInstanceActivity taskId: 40513 hashCode: 240431118
  15. 2020-04-29 16:40:16.819 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onSaveInstanceState: SingleInstanceActivity taskId: 40513 hashCode: 240431118
  16. 2020-04-29 16:40:16.823 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onStop: SingleInstanceActivity taskId: 40513 hashCode: 240431118
  17. 2020-04-29 16:40:31.888 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onNewIntent: SingleInstanceActivity taskId: 40513 hashCode: 240431118
  18. 2020-04-29 16:40:31.889 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: taskAffinity: com.lyf.test.singleinstancedemo
  19. 2020-04-29 16:40:31.892 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onRestart: SingleInstanceActivity taskId: 40513 hashCode: 240431118
  20. 2020-04-29 16:40:31.893 16149-16149/com.lyf.launchmodektdemo I/LaunchMode: onStart: SingleInstanceActivity taskId: 40513 hashCode: 240431118
  21. 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在系统中具有全局唯一性。

  1. 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. JS、JSP、ASP、CGI

      1)JS是在客户端执行的,需要浏览器支持Javascript.JSP是在服务器端执行的,需要服务器上部署支持Servlet的服务器程序.JS代码是能够直接从服务器上download得到,对外是可见 ...

  2. innodb mvcc多版本实现

    出自:http://hedengcheng.com/?p=148 基本知识 假设对于多版本(MVCC)的基础知识,有所了解.InnoDB为了实现多版本的一致读,采用的是基于回滚段的协议. 行结构 In ...

  3. asp.net 重写URL方法和封装好的DLL

    .net 重写URL方法和封装好的DLL URL重写方法DLL(2.0)

  4. day2(基础数据类型)

    一.基础数据类型操作 1.数字 int 数字主要是用于计算用的,使用方法并不是很多,就记住一种就可以: int.bit_length() -> int Number of bits necess ...

  5. 适配android和iOS上position:absolute和input问题

    //适配android上absolute和input的问题var oHeight = $(document).height(); //屏幕当前的高度$(window).resize(function( ...

  6. Java理论学时第五节。课后作业。

    随机生成10个数,填充一个数组,然后用消息框显示数组内容,接着计算数组元素的和,将结果也显示在消息框中. 设计思路:先声明一个数组,再利用for循环对每一个元素赋随机生成的值,在求所有数的和,再根据要 ...

  7. SSM_CRUD新手练习(2)配置文件

    配置之前现需要引入依赖的jar包: *Spring *SpringMvc *Mybatis *数据库连接池,驱动包 *其他(jstl,Servlet ,Junit..) 1.poxm.xml < ...

  8. SPRING框架中ModelAndView、Model、ModelMap区别及详细分析

    转载内容:http://www.cnblogs.com/google4y/p/3421017.html 1. Model Model 是一个接口, 其实现类为ExtendedModelMap,继承了M ...

  9. SRM478

    又是rng_58的神题.. 250pt: 题意:给定一个初始数x,对于这个数可以进行x*4+3,或者x*8+7的操作.最多进行100000次操作 问最少经过几次出现%1000000007 == 0的情 ...

  10. EBS 取消“是否提交另一项请求”提示

    在使用EBS提交请求后,总要弹出“是否提交另一项请求”的提示,而我们往往选择“否”,这个提示就显得多余. 为了减轻这“多一步”的负担,取消“是否提交另一项请求”的提示,设置方法如下: 以下profil ...