如何用活动结果 API 替换 startActivityForResult?

Neo*_*eoh 22 android android-activity onactivityresult androidx

我有一个主要活动,它作为根据条件调用不同活动的入口点。其中,我使用 Firebase Auth 来管理用户登录:

startActivityForResult(
            AuthUI.getInstance().createSignInIntentBuilder()
                    .setAvailableProviders(providers)
                    .build(),
            RC_SIGN_IN)
Run Code Online (Sandbox Code Playgroud)

我覆盖onActivityResult()以区分返回的意图/数据,例如:

 override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    when (requestCode) {

        REQUEST_CODE_1 -> {
          // update UI and stuff
        }

        RC_SIGN_IN -> {
          // check Firebase log in
        }
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

使用文档强烈推荐的 Activity Result APIs ,我知道我应该在启动prepareCall()之前创建ActivityResultLauncher并确保活动在启动时处于创建状态,但我仍然不明白如何优雅地处理多个活动结果(在至少,在一个地方)就像在onActivityResult().

这篇文章,似乎我需要实现多个ActivityResultContract类型的子内部类(因此是多个prepareCall()?),因为它们应该是不同的合同,我说得对吗?有人可以向我展示一些反映上述onActivityResult()逻辑的骨架示例吗?

Mis*_*pov 20

您可以根据需要调用任意数量的活动以获得结果,并为每个活动设置单独的回调:

    val startForResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult())
    { result: ActivityResult ->
        if (result.resultCode == Activity.RESULT_OK) {
            //  you will get result here in result.data
            }

        }
    }

    startForResult.launch(Intent(activity, CameraCaptureActivity::class.java))
Run Code Online (Sandbox Code Playgroud)

您只需要指定 Activity 类 - CameraCaptureActivity::class.java

更新:

The prepareCall() method has been renamed to registerForActivityResult() in Activity 1.2.0-alpha04 and Fragment 1.3.0-alpha04. And it should be startForResult.launch(...) in the last line

感谢 拉斐尔·塔瓦雷斯( Rafael Tavares)的更新

  • 在 [Activity `1.2.0-alpha04`](https://developer.android.com/jetpack/androidx/releases/activity#1.2.0-) 中,`prepareCall()` 方法已重命名为 `registerForActivityResult()` alpha04)和[片段`1.3.0-alpha04`](https://developer.android.com/jetpack/androidx/releases/fragment#1.3.0-alpha04)。最后一行应该是`startForResult.launch(...)` (2认同)
  • 将“android.content.Intent Intent, int requestCode”作为参数传递怎么样? (2认同)

Har*_*ara 12

从现在开始,startActivityForResult()已被弃用,因此请使用新方法而不是新方法。

例子

public void openActivityForResult() {
    
 //Instead of startActivityForResult use this one
        Intent intent = new Intent(this,OtherActivity.class);
        someActivityResultLauncher.launch(intent);
    }


//Instead of onActivityResult() method use this one

    ActivityResultLauncher<Intent> someActivityResultLauncher = registerForActivityResult(
            new ActivityResultContracts.StartActivityForResult(),
            new ActivityResultCallback<ActivityResult>() {
                @Override
                public void onActivityResult(ActivityResult result) {
                    if (result.getResultCode() == Activity.RESULT_OK) {
                        // Here, no request code
                        Intent data = result.getData();
                        doSomeOperations();
                    }
                }
            });
Run Code Online (Sandbox Code Playgroud)

  • 感谢您不使用“var”和 lambda :) (6认同)

Kri*_*ony 11

首先,不要忘记将此添加到您的 Gradle 依赖项中

implementation 'androidx.activity:activity-ktx:1.2.0-alpha05'
implementation 'androidx.fragment:fragment-ktx:1.3.0-alpha05'
Run Code Online (Sandbox Code Playgroud)

其次,通过扩展一个名为ActivityResultContract<I, O>. 我的意思是输入的类型,O 的意思是输出的类型。然后你只需要覆盖2个方法

class PostActivityContract : ActivityResultContract<Int, String?>() {

    override fun createIntent(context: Context, input: Int): Intent {
        return Intent(context, PostActivity::class.java).apply {
            putExtra(PostActivity.ID, postId)
        }
    }

    override fun parseResult(resultCode: Int, intent: Intent?): String? {
        val data = intent?.getStringExtra(PostActivity.TITLE)
        return if (resultCode == Activity.RESULT_OK && data != null) data
        else null
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,最后一步是将合约注册到Activity. 您需要将自定义合同和回调传递到registerForActivityResult.

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
      
        start_activity_contract.setOnClickListener {
            openPostActivityCustom.launch(1)
        }
    }
  
    // Custom activity result contract
    private val openPostActivityCustom =
        registerForActivityResult(PostActivityContract()) { result ->
            // parseResult will return this as string?                                              
            if (result != null) toast("Result : $result")
            else toast("No Result")
        }
}
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请查看此帖子


nyx*_*xee 5

在这种情况下,AuthUI 返回的已经是一个 Intent,因此,我们像下面的示例一样使用它。

private val startForResult =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
            when(result.resultCode){
                RESULT_OK -> {
                    val intent = result.data
                    // Handle the Intent...
                    mUser = FirebaseAuth.getInstance().currentUser
                }
                RESULT_CANCELED -> {

                } else -> {
            } }
        }
Run Code Online (Sandbox Code Playgroud)

使用以下命令从任何地方(例如单击按钮)启动活动:

 AuthUI.getInstance().createSignInIntentBuilder().setAvailableProviders(providers)
            .build().apply {
                startForResult.launch(this)
            }
Run Code Online (Sandbox Code Playgroud)