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

Android 如何用活动结果API替换startActivityForResult?,android,android-activity,androidx,onactivityresult,Android,Android Activity,Androidx,Onactivityresult,我有一个主活动,它作为一个入口点,根据条件调用不同的活动。其中,我使用Firebase Auth管理用户登录: startActivityForResult( AuthUI.getInstance().createSignInIntentBuilder() .setAvailableProviders(providers) .build(), RC_SIGN_IN)

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

startActivityForResult(
            AuthUI.getInstance().createSignInIntentBuilder()
                    .setAvailableProviders(providers)
                    .build(),
            RC_SIGN_IN)
我覆盖ActivityResult()以区分返回的意图/数据,例如:

 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
        }
        // ...
    }
}
通过的强烈推荐的活动结果API,我知道我应该在
ActivityResultLauncher
之前进行
prepareCall()
,并确保在启动时活动处于创建状态,但我仍然不知道如何优雅地处理多个活动结果(至少在一个地方)类似于onActivityResult()中的


现在来看,似乎我需要实现多个
ActivityResultContract
类型的子内部类(因此有多个
prepareCall()
),因为它们应该是不同的契约,对吗?有人能给我看一些反映上述
onActivityResult()
逻辑的框架示例吗?

您可以根据需要调用任意多个活动以获得结果,并且每个活动都有单独的回调:

    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))
您只需要指定活动类-
CameraCaptureActivity::class.java

更新:

在活动1.2.0-alpha04和片段1.3.0-alpha04中,prepareCall()方法已重命名为registerForActivityResult()。最后一行应该是startForResult.launch(…)


感谢Rafael Tavares的更新

在本例中,AuthUI返回的内容已经是一个意图,因此,我们像下面的示例一样使用它

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 -> {
            } }
        }
使用以下命令从任何位置(例如,单击按钮)启动活动:


从现在起,
startActivityForResult()
已被弃用,因此请使用新方法

示例

public void openActivityForResult(){
//使用此选项代替startActivityForResult
意向意向=新意向(this,OtherActivity.class);
someActivityResultLauncher.launch(意图);
}
//使用以下方法代替onActivityResult()方法
ActivityResultLauncher someActivityResultLauncher=registerForActivityResult(
新ActivityResultContracts.StartActivityForResult(),
新ActivityResultCallback(){
@凌驾
ActivityResult上的公共无效(ActivityResult结果){
if(result.getResultCode()==Activity.result\u确定){
//这里没有请求代码
Intent data=result.getData();
doSomeOperations();
}
}

});如果从片段启动活动并将结果返回到片段,请执行此操作

片段:

private lateinit var activityResult: ActivityResultLauncher<Intent>

activityResult = registerForActivityResult(
    ActivityResultContracts.StartActivityForResult()) { result ->
    if (result.resultCode == RESULT_OK) {
        val data = result.data
        doSomeOperations(data)
    }
}

SomeActivity.showScreen(activityResult, requireContext())
private lateinit var activityResult:ActivityResultLauncher
activityResult=registerForActivityResult(
ActivityResultContracts.StartActivityForResult()){result->
if(result.resultCode==result\u OK){
val数据=结果数据
doSomeOperations(数据)
}
}
SomeActivity.showScreen(activityResult,requireContext())
在活动中:

// activity?.setResult(Activity.RESULT_OK) doesn't change.

companion object {

    fun showScreen(activityResult: ActivityResultLauncher<Intent>, context: Context) {
        val intent = Intent(context, SomeActivity::class.java)
        activityResult.launch(intent)
    }
}
//activity?.setResult(activity.RESULT\u OK)不会更改。
伴星{
有趣的显示屏幕(activityResult:ActivityResultLauncher,上下文:上下文){
val intent=intent(上下文,SomeActivity::class.java)
activityResult.launch(意图)
}
}
首先,别忘了将其添加到Gradle依赖项中

其次,通过扩展名为
ActivityResultContract
的抽象类来创建结果契约。我指的是输入类型,O指的是输出类型。然后只需要重写2个方法


有关更多信息,请查看此列表

和中的
prepareCall()
方法已重命名为
registerForActivityResult()
。最后一行应该是
startForResult.launch(…)
,将
'android.content.Intent Intent,int requestCode'
作为参数传递怎么样?但是,为了从Activity2返回结果,与往常一样?:setResult(Bundle)??请使用google signin Activityforresult尝试此代码,但运气不佳,有什么建议吗?这个代码对我有用;但我必须翻译成科特林。谢谢
// activity?.setResult(Activity.RESULT_OK) doesn't change.

companion object {

    fun showScreen(activityResult: ActivityResultLauncher<Intent>, context: Context) {
        val intent = Intent(context, SomeActivity::class.java)
        activityResult.launch(intent)
    }
}
implementation 'androidx.activity:activity-ktx:1.2.0-alpha05'
implementation 'androidx.fragment:fragment-ktx:1.3.0-alpha05'
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
    }
}
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")
        }
}
List<AuthUI.IdpConfig> providers = Arrays.asList(
                    new AuthUI.IdpConfig.EmailBuilder().build(),
                    new AuthUI.IdpConfig.GoogleBuilder().build());

            ActivityResultLauncher<Intent> launcher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
                if (result.getResultCode() == Activity.RESULT_OK) {
                    Log.v("LOGIN OK", "OK Result for Login");
                }
            });
            
            launcher.launch(AuthUI.getInstance()
                    .createSignInIntentBuilder()
                    .setIsSmartLockEnabled(false)
                    .setAvailableProviders(providers)
                    .build());