通过 Intent 从 activity A->B->C- 切换回 A 与多次调用 finish() 之间的区别

Difference between switching from activity A->B->C- back to A via Intent vs several calls to finish()

假设我有三个活动 ABC 用于以下方式。您从 activity A 开始,然后按一个按钮将您带到 B,然后再按另一个按钮将您带到 C。现在在 C 上你已经完成并想返回 A。可能有很多方法可以做到这一点,但我感兴趣的是通过 Intent 返回 A 与使用 之间的区别]完成().

使用意图: Intent(this, A::class.java).also { startActivity(it) }

使用 finish(): 为了正确地回到 A,我相信我必须做这样的事情。

// Activity_B.kt
...
override fun onResume() {
    super.onResume()
    if(resumed > 0) { // resumed is "private var resumed: Int = 0"
        // Next time we resume, we'll enter here.
        // Specifically, we end up here after C calls finish()
        finish() // This takes us back to activity A.
    } else {
        // End up here after first time A is created
        resumed++
    }
}
// Activity_C.kt
...
    finish() // This takes us back to Activity_B and onResume() is called
...

使用 Intents 我们会立即在 A 中结束,而如果我们以第二种方式进行,我们必须先通过 B 返回.我的问题是一个是否比另一个更合适?出于某种原因,使用 finish() 的第二种方式感觉更自然,因为我们通过完成活动的使用回溯,而在使用意图时感觉就像我们“让活动等待和未完成“ 在某种意义上。在“幕后”的行为上真的有区别还是等同的?

如果我理解你的问题,我认为 finish() 只是调用当前 activity 的 finish() 方法。如果您想转到特定的 activity,意图是最好和合适的方法。当然有旗帜。

我不知道你为什么需要 OnResume()。

通常最好使用 startActivity(intent);然后调用 finish();这样当前的 activity 就不会留在后台。除非你当然想要那个。

ps。从 Java 的角度来谈谈这里。不知道在Kotlin里是不是一样

 onButtonClick(View v){
  Intent intent=new Intent(context,targetactivity.class);
  // if you want put your Flags actions or Extras here...

  //start target activity.
  startActivity(intent);

  // finish current activity
  // this is just to finish the current activity and ha no control
  // on where you end up.
  finish()
  }

并且可以覆盖 onBackPressed()

主要区别在于您在 back stack 中的最终结果。如果您使用意图返回 A,您最终会得到 [A, B, C, A] 的返回堆栈,这意味着如果用户在执行此操作后按下 phone 上的后退按钮,他们将回到 C。再次按回键会将它们带回 B。根据这些活动是什么,这可能是也可能不是期望的行为。

如果您使用 finish(),活动将从返回堆栈中删除,因此返回到 A 后,您的返回堆栈将不包括 BC,它只是 [A] 但是,您应该使用 onActivityResult 回调或在移动到 C 之前完成 B 而不是依赖 onResume 。使用 onResume 会产生意想不到的副作用,例如,如果用户在 Activity B 上最小化您的应用程序(例如查看他们的电子邮件或接听电话) - 当他们回到您的应用程序时,它会调用onResume 并错误地触发 finish()

方法一-Activity结果回调

这个流程是:

  1. ActivityA开始activityB
  2. Activity B 使用 appropriate onActivityResult callback 启动 activity C。在此回调中,activity B 将在通知 C 已完成时调用 finish()
  3. 当 activity C 完成时,它将其结果状态设置为完成 (RESULT_OK) 并调用 finish() - 这将通知 activity B 它也必须致电 finish()

例如,这些将在 Activity B:

// Activity B
var goToC = registerForActivityResult(StartActivityForResult()) { result ->
    if (result.resultCode == Activity.RESULT_OK) {
         // This will be called when C is completed
         finish();
    }
}
 
private fun goToActivityC() {
    val intent = Intent(this, ActivityC::class.java)
    goToC.launch(intent)
}

当 activity C 完成时,您将调用此方法来设置其结果并自行完成(将应用程序带回 B 并立即触发上面的回调)。请注意,如果用户按回键,则不会设置结果,他们只会返回 B 而不会触发回调。

// Activity C
private fun allDone() {
    Intent data = Intent()
    setResult(Activity.RESULT_OK, data)
    finish()
}

方法 2 - 在启动 C 之前完成 B

另一种替代方法是在开始 C 之前先完成 B,这样 Activity B 就会使用

private fun goToActivityC() {
    val intent = Intent(this, ActivityC::class.java)
    startActivity(intent)
    finish() // finish and remove B from the back stack
    // back stack will now be [A, C]
}

并在 Activity C

private fun allDone() {
    finish() // finish and remove C from the back stack
    // Will take you back to A and back stack will be just [A]
}

这种方法的主要缺点是,如果用户在 C 上按下返回键,他们将返回到 A,而不是 B。这可能不是直观的行为(实际上取决于这些活动是什么)。