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

xzlaal3s  于 2023-01-11  发布在  Android
关注(0)|答案(7)|浏览(131)

我有一个主Activity,它作为一个入口点,可以根据情况调用不同的Activity。其中,我使用Firebase Auth来管理用户登录:

startActivityForResult(
            AuthUI.getInstance().createSignInIntentBuilder()
                    .setAvailableProviders(providers)
                    .build(),
            RC_SIGN_IN)

我覆盖onActivityResult()以区分返回的intent/data,例如:

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
        }
        // ...
    }
}

使用documentation强烈推荐的Activity Result API,我知道我应该在ActivityResultLauncher之前创建prepareCall(),并确保Activity在启动时处于已创建状态,但我仍然不明白如何像onActivityResult()那样优雅地处理多个Activity结果(至少在一个位置)。
看一下this article,我似乎需要实现ActivityResultContract类型的 * 多个 * 子内部类(因此是多个prepareCall()?),因为它们应该是不同的 * 契约 *,我说的对吗?有人能给我一些反映上述onActivityResult()逻辑的框架示例吗?

ttvkxqim

ttvkxqim1#

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

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(...)

jxct1oxe

jxct1oxe2#

从现在起,startActivityForResult()已被弃用,因此请使用new方法代替。

    • 示例**
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();
                    }
                }
            });
cuxqih21

cuxqih213#

  • 首先,不要忘记将此添加到您的Gradle依赖项中 *
implementation 'androidx.activity:activity-ktx:1.2.0-alpha05'
implementation 'androidx.fragment:fragment-ktx:1.3.0-alpha05'
  • 其次,通过扩展一个名为ActivityResultContract<I, O>的抽象类来创建结果契约。I表示输入类型,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
    }
}
  • 最后,最后一步是将合约注册到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")
        }
}

有关更多信息,请查看此Post

g9icjywg

g9icjywg4#

在本例中,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 -> {
            } }
        }

使用以下命令从任意位置(例如单击按钮)启动活动:

AuthUI.getInstance().createSignInIntentBuilder().setAvailableProviders(providers)
            .build().apply {
                startForResult.launch(this)
            }
ikfrs5lh

ikfrs5lh5#

如果从片段启动Activity并将结果返回给片段,请执行以下操作。
片段:

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

活动中:

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

nnsrf1az6#

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());

更多详情请参见:https://githubmemory.com/repo/firebase/FirebaseUI-Android/issues?cursor=Y3Vyc29yOnYyOpK5MjAyMS0wMy0wNVQyMjoxNzozMyswODowMM4xEAQZ&pagination=next&page=2

fcipmucu

fcipmucu7#

将其用于Firebase AuthUI;

final ActivityResultLauncher<Intent> launcher = registerForActivityResult(
            new FirebaseAuthUIActivityResultContract(), this::onSignInResult);

    binding.loginSignup.setOnClickListener(view -> {
        List<AuthUI.IdpConfig> provider = Arrays.asList(new AuthUI.IdpConfig.EmailBuilder().build(),
                new AuthUI.IdpConfig.GoogleBuilder().build(),
                new AuthUI.IdpConfig.PhoneBuilder().build());
        Intent intent = AuthUI.getInstance()
                .createSignInIntentBuilder()
                .setIsSmartLockEnabled(false)
                .setAlwaysShowSignInMethodScreen(true)
                .setAvailableProviders(provider)
                .build();
        launcher.launch(intent);
    });

private void onSignInResult(FirebaseAuthUIAuthenticationResult result) {

    if (result.getResultCode() == RESULT_OK) {
        FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
        if (user != null) {
            if (user.getMetadata() != null) {
                if (user.getMetadata().getCreationTimestamp() != user.getMetadata().getLastSignInTimestamp()) {
                    Toast.makeText(this, "Welcome Back", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(this, "Welcome", Toast.LENGTH_SHORT).show();
                }
                startMainActivity();
            }
        }
    } else {
        IdpResponse response = result.getIdpResponse();
        if (response == null)
            Toast.makeText(this, "Canceled By You", Toast.LENGTH_SHORT).show();
        else Log.d(TAG, "onCreate: ActivityResult" + response.getError());
    }
}

private void startMainActivity() {
    Intent intent = new Intent(LoginActivity.this, MainActivity.class);
    startActivity(intent);
    finish();
}

像这样。

相关问题