简化Activity跳转与结果回传(startActivityForResult & Activity Result API)

使用举例

实现原理

通过封装Activity Result API,将Intent中的参数全部放在一个Parcelable对象上(这个对象的key是特殊的_extra_),而不是将参数一个一个的通过intent.putExtra()来传递, 可以减少很多静态变量如INTENT_KEY_XX的声明

具体代码

kotlin 复制代码
// ActivityResultKt.kt类
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Parcelable
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResult
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContract

const val INTENT_EXTRA = "_extra_"

fun <PI : Parcelable?, PO : Parcelable> ComponentActivity.registerResult(
    activityClass: Class<*>,
    onResult: (resultCode: Int, out: PO?) -> Unit
): ActivityResultLauncher<PI?> {
    return registerForActivityResult(StartActivityForResultContract(activityClass)) { r ->
        val ext = r.data?.getParcelableExtra(INTENT_EXTRA) as? PO
        onResult(r.resultCode, ext)
    }
}

class StartActivityForResultContract<T : Parcelable?>(private val activityClass: Class<*>) :
    ActivityResultContract<T, ActivityResult>() {
    override fun createIntent(context: Context, input: T): Intent {
        val intent = Intent(context, activityClass)
        intent.putExtra(INTENT_EXTRA, input)
        if (context !is Activity) {
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        }
        return intent
    }

    override fun parseResult(resultCode: Int, intent: Intent?): ActivityResult = ActivityResult(resultCode, intent)
}

fun <PI : Parcelable?> ComponentActivity.getExtra(): PI? = intent.getParcelableExtra(INTENT_EXTRA) as? PI

fun <PO : Parcelable> ComponentActivity.setResult(resultCode: Int, out: PO) {
    val intent = Intent()
    intent.putExtra(INTENT_EXTRA, out)
    setResult(resultCode, intent)
}

如何使用

  1. 将以上ActivityResultKt.kt类复制到项目中, Fragment请自行实现
  2. 定义ActivityB需要的输入参数类,例如参数有studentId
kotlin 复制代码
@Parcelize // 该注解来自 id 'kotlin-parcelize' 插件
data class InExtra(val studentId: String): Parcelable
  1. 定义ActivityA需要的返回结果类,例如需要studentName
kotlin 复制代码
@Parcelize
data class OutExtra(val studentName: String): Parcelable
  1. ActivityA定义启动器
kotlin 复制代码
// 若不需要输入,可以填Nothing, registerResult<Nothing, OutExtra>
val activityLauncher = registerResult<InExtra, OutExtra>(ActivityB::class.java) { resultCode, out ->

}
  1. 在需要的地方跳转到ActivityB
kotlin 复制代码
activityLauncher.launch(InExtra(studentId = "123"))
  1. ActivityB中将结果返回
kotlin 复制代码
// val inExtra = getExtra<InExtra>() 取出输入值
setResult(RESULT_OK, OutExtra(studentName = "飞羽"))
finish()
相关推荐
毕设源码-郭学长42 分钟前
【开题答辩全过程】以 基于Android的点餐APP的设计为例,包含答辩的问题和答案
android
polaris063044 分钟前
学生成绩管理系统(MySQL)
android·数据库·mysql
__Yvan1 小时前
Kotlin 的 ?.let{} ?: run{} 真的等价于 if-else 吗?
android·开发语言·前端·kotlin
tangweiguo030519871 小时前
Android WorkManager 完整实战教程(含完整文件)
android·kotlin
loitawu2 小时前
Rockchip Android16 系统裁剪指南
android·android16·android裁剪·系统裁剪·rockchip app
小羊子说2 小时前
关于车机中的升级流程小结(SOC、MCU、4G升级流程)
android·adb·性能优化·车载系统
肖。35487870943 小时前
[技巧-11]AndroidManifest.xml完善小技巧。
android
小羊子说3 小时前
Android 车机开发中常用的adb 脚本(更新中)
android·linux·adb·性能优化·车载系统
用户7607495397833 小时前
Android页面四大布局运行结果
android
风往哪边走3 小时前
搜索框自定义
android