从服务中使用FLAG_ACTIVITY_REORDER_TO_FRONT调用活动

8
我正在尝试从一个服务中调用一个活动(活动A),我想要的是检查堆栈中是否已经有A的实例,如果有,则将其置于堆栈顶部(并触发onNewIntent()方法),而不是总是创建A的新实例。想知道这是否可行。我的活动在androidmanifest中使用了"singleTop"启动模式。通常用于从活动外部调用活动的Intent.FLAG_ACTIVITY_NEW_TASK标志不会将已打开的活动A置于堆栈顶部,而是总是创建A的新实例。此外,当我同时使用两个标志(intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT))时,仍然会发生同样的事情(仍然有2个相同活动的实例)。有方法可以做到这一点吗?请始终记住,我是从服务中进行调用的,我不想将活动上下文传递给服务。(附注:我正在使用androidannotations,打开活动A的调用发生在@EBean内部,该@EBean本身被用于服务。有没有一种简单的方式来将活动上下文传递给@EBean?)

您可以使用@RootContext。 - WonderCsabo
当从服务启动时,@RootContext不是Activity的实例。因此它无法工作,仍然需要FLAG_ACTIVITY_NEW_TASK。 - sakis kaliakoudas
抱歉,如果您将Bean注入到Service中,那么@RootContext当然就是Service。 - WonderCsabo
我也遇到了同样的问题。你找到解决方案了吗?你最终使用了哪个上下文? - seekingStillness
如果您没有任何可能需要两个实例的情况,那么您是否尝试使用singleInstance启动模式呢? - Goodie123
1个回答

4

如果你想使用非活动的context(例如applicationContext)启动活动,从而使用Intent.FLAG_ACTIVITY_NEW_TASK,则只有两种选择可以避免每次调用startActivity时创建目标活动的新实例。

首先,在清单文件中为活动指定android:launchMode="singleInstance",可以强制在仅托管此实例的任务中存在该活动的唯一实例。在这种情况下,如果它已经存在于主任务中,则启动该活动将其带到前台,否则会创建一个新任务,其中包含该活动的唯一实例。我认为这不是我们要寻找的方式。

其次,通过在清单文件中指定android:launchMode="singleTask",我们可以实现更好的解决方案。在这种情况下,如果不存在该活动的实例,则系统将创建一个新任务,并将该活动添加到该任务的根位置。否则,系统会将包含该活动实例的任务置于前台,然后转到目标活动并调用onNewIntent

下面是第二种方法的示例代码,检查了2个场景:

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)
            }
        }
    }
}

结果:

.......


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接