大家更新了SDK后,应该都发现了之前用的很多的startActivityForResult和onActivityResult方法已经声明已废弃了,在查看源码后,我们可以看到onActivityResult方法上声明了@Deprecated,建议我们使用Activity Result API来代替
/**
* {@inheritDoc}
*
* @deprecated This method has been deprecated in favor of using the Activity Result API
* which brings increased type safety via an {@link ActivityResultContract} and the prebuilt
* contracts for common intents available in
* {@link androidx.activity.result.contract.ActivityResultContracts}, provides hooks for
* testing, and allow receiving results in separate, testable classes independent from your
* activity. Use
* {@link #registerForActivityResult(ActivityResultContract, ActivityResultCallback)}
* passing in a {@link StartActivityForResult} object for the {@link ActivityResultContract}.
*/
@Override
@Deprecated
public void startActivityForResult(@SuppressLint("UnknownNullness") Intent intent,
int requestCode) {
super.startActivityForResult(intent, requestCode);
}
/**
* {@inheritDoc}
*
* @deprecated This method has been deprecated in favor of using the Activity Result API
* which brings increased type safety via an {@link ActivityResultContract} and the prebuilt
* contracts for common intents available in
* {@link androidx.activity.result.contract.ActivityResultContracts}, provides hooks for
* testing, and allow receiving results in separate, testable classes independent from your
* activity. Use
* {@link #registerForActivityResult(ActivityResultContract, ActivityResultCallback)}
* with the appropriate {@link ActivityResultContract} and handling the result in the
* {@link ActivityResultCallback#onActivityResult(Object) callback}.
*/
@CallSuper
@Override
@Deprecated
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
if (!mActivityResultRegistry.dispatchResult(requestCode, resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
}
}
我们可以直接使用registerForActivityResult来代替startActivityForResult
lateinit var activityResultLauncher: ActivityResultLauncher
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityResultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
// 处理回调
}
// 跳转页面
activityResultLauncher.launch(Intent(this, SecondActivity::class.java))
}
但是这种方法有个弊端,如果我们有多个页面跳转的话,我们无法在同一个activityResultLauncher的回调中判断是来自哪一个的回调,因为缺少了requestCode,这时候我们只能通过注册多个来解决这个问题,这样不是比之前更麻烦了么,有没有更好的办法呢?
@NonNull
@Override
public final ActivityResultLauncher registerForActivityResult(
@NonNull final ActivityResultContract contract,
@NonNull final ActivityResultRegistry registry,
@NonNull final ActivityResultCallback callback) {
return registry.register(
"activity_rq#" + mNextLocalRequestCode.getAndIncrement(), this, contract, callback);
}
@NonNull
@Override
public final ActivityResultLauncher registerForActivityResult(
@NonNull ActivityResultContract contract,
@NonNull ActivityResultCallback callback) {
return registerForActivityResult(contract, mActivityResultRegistry, callback);
}
我们继续看源码发现,registerForActivityResult其实是调用ActivityResultRegistry来注册的,而ActivityResultRegistry我们是可以直接获取到的,我们可以自己封装一下
private val requestCode = AtomicInteger()
private val key: String get() = "activity_rq#${requestCode.getAndIncrement()}"
val activityContracts = ActivityResultContracts.StartActivityForResult()
suspend fun ComponentActivity.launch(
contract: ActivityResultContract,
input: I
): O {
var caller: ActivityResultLauncher? = null
return suspendCancellableCoroutine { continuation ->
caller = activityResultRegistry.register(key, contract) {
continuation.resume(it)
}.apply {
launch(input)
}
}.also {
caller?.unregister()
caller = null
}
}
fun ComponentActivity.launch(
contract: ActivityResultContract,
input: I,
output: ActivityResultCallback
) {
var caller: ActivityResultLauncher? = null
caller = activityResultRegistry.register(key, contract) {
output.onActivityResult(it)
caller?.unregister()
caller = null
}.apply {
launch(input)
}
}
/**
* 启动activity获取返回值
*/
fun ComponentActivity.launchActivityForResult(
intent: Intent,
output: ActivityResultCallback
) = launch(activityContracts, intent, output)
使用方法如下
// 正常使用
launchActivityForResult(Intent(this, SecondActivity::class.java)) {
// 处理回调
}
// 在协程中使用
lifecycleScope.launch {
val activityResult = launch(
contract = activityContracts,
input = Intent(this@MainActivity, SecondActivity::class.java)
)
// 处理回调
}
看起来是不是简洁很多了,而且代码逻辑也清晰不少。
ActivityResultContracts中,除了StartActivityForResult外,还内置了一些常用的
页面更新:2024-04-01
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号