Since you want to use a non-activity context
(e.g. applicationContext
) to start the activity leading to use Intent.FLAG_ACTIVITY_NEW_TASK
, you have only two choices to avoid creating a new instance of the target activity every time you're calling startActivity
.
First, by specifying android:launchMode="singleInstance"
in the manifest for the activity, you can force that only one instance of the activity should exist in a task that hosts only this instance. In this case, starting the activity brings it to the front if there exists in the host task, otherwise, a new task gets created containing the only instance of the activity. I think it's not the way we are looking for.
Second, by specifying android:launchMode="singleTask"
in the manifest for the activity, we can achieve a better solution. In this case, the system creates a new task and adds the activity at the root of this task, if there exists no instance of the activity. Otherwise, the system brings the task containing the activity instance to the front then routes to the target activity, and calls onNewIntent
.
Here is an example code of the second approach, examines 2 scenarios:
manifest.xml:
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ActivityA" android:launchMode="singleTask" />
<activity android:name=".ActivityB" />
MainActivity.kt:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// First Scenario: ActivityA doesn't exist in back-stack
button1.setOnClickListener {
Intent(applicationContext, ActivityA::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK
}.let {
applicationContext.startActivity(it)
}
}
// Second Scenario: ActivityA exists in back-stack
button2.setOnClickListener {
startActivity(Intent(this, ActivityA::class.java))
// Start ActivityB after a while
Handler().postDelayed({
startActivity(Intent(this, ActivityB::class.java))
}, 1000)
}
}
}
ActivityA.kt
class ActivityA : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_a)
Toast.makeText(this, "onCreate on ActivityA", Toast.LENGTH_SHORT).show()
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
Toast.makeText(this, "onNewIntent on ActivityA", Toast.LENGTH_SHORT).show()
}
}
ActivityB.kt
class ActivityB : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_b)
button.setOnClickListener {
Intent(applicationContext, ActivityA::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK
}.let {
applicationContext.startActivity(it)
}
}
}
}
Result:
.......