我正在尝试从服务调用一个活动(活动A),我想要发生的是检查堆栈上是否已经存在A的实例,如果有,则将其带到顶部stack(并触发onNewIntent()方法),而不是始终创建A的新实例。
想知道这是否可行。我的活动在androidmanifest中使用“singleTop”启动模式。从活动外部调用活动所需的通常的Intent.FLAG_ACTIVITY_NEW_TASK标志不会将已打开的活动A带到堆栈的顶部,但总是创建一个新的A实例。当我同时使用它们时flags(intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)同样的事情发生了(仍然是同一活动的2个实例)。有没有办法去做这件事,总是记住我正在进行呼叫服务,我不想将活动上下文传递给服务?
(PS我正在使用androidannotations,对开放活动A的调用发生在@EBean中,它本身用于服务。是否有一种简单的方法以某种方式将该活动上下文传递给该@EBean?)
答案 0 :(得分:5)
由于您要使用非活动context
(例如applicationContext
)来启动导致使用Intent.FLAG_ACTIVITY_NEW_TASK
的活动,因此只有两个选择可以避免创建新的实例您每次致电startActivity
时的目标活动。
首先,通过在活动清单中指定android:launchMode="singleInstance"
,可以强制在仅承载该实例的任务中仅存在该活动的一个实例。在这种情况下,如果宿主任务中存在活动,则启动活动将其置于最前面,否则,将创建一个包含活动唯一实例的新任务。我认为这不是我们想要的方式。
第二,通过在清单中为活动指定android:launchMode="singleTask"
,我们可以获得更好的解决方案。在这种情况下,如果不存在活动实例,则系统将创建一个新任务并将该活动添加到该任务的根目录。否则,系统会将包含活动实例的任务放在最前面,然后路由到目标活动,并调用onNewIntent
。
这是第二种方法的示例代码,检查了两种情况:
<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" />
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)
}
}
}
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()
}
}
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)
}
}
}
}
.......