简化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()
相关推荐
方白羽8 分钟前
Android多层嵌套RecyclerView滚动
android·java·kotlin
菜就多学1 小时前
SurfaceControlViewHost 实现跨进程UI渲染
android·设计
2501_915106321 小时前
iOS App 测试工具全景分析,构建从开发调试到线上监控的多阶段工具链体系
android·测试工具·ios·小程序·uni-app·iphone·webview
小羊在奋斗2 小时前
MySQL表的约束:从基础到核心(附场景+案例)
android·数据库·mysql
e***19353 小时前
MySQL-mysql zip安装包配置教程
android·mysql·adb
方白羽3 小时前
Kotlin遇上Java 静态方法
android·java·kotlin
q***06474 小时前
SpringSecurity相关jar包的介绍
android·前端·后端
7***31885 小时前
若依微服务中配置 MySQL + DM 多数据源
android·mysql·微服务
我是好小孩5 小时前
【Android】常见的架构模式:MVC, MCP, MVVM
android·架构·mvc
Digitally5 小时前
如何通过蓝牙将联系人从 iPhone 传输到 Android
android·ios·iphone