简化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()
相关推荐
笑一下蒜了.2 分钟前
Linux 存储多路径访问手册|multipath.conf 各配置段详解
android·linux·运维
凡泰AI5 分钟前
如何通过小程序多端框架,让一个小程序同时运行在iOS、安卓、鸿蒙以及PC客户端,实现一次开发多端运行的效果
android·ios·小程序
一笑的小酒馆1 小时前
Androidiot扫地机器人设备详情页地图加载慢卡顿优化方案
android
Zhu7587 小时前
在k8s集群部署MySQL单实例,支持多个主流发行版
android·mysql·kubernetes
AFinalStone10 小时前
Android 7系统异常问题排查(四)Framework层(上)—System Server Watchdog
android·系统异常
宝杰X711 小时前
Android Room3 多平台数据库
android·数据库
huibin14785236914 小时前
热缓解学习记录
android·学习
我命由我1234517 小时前
匈牙利命名法
java·服务器·后端·学习·java-ee·kotlin·学习方法
小田的博客17 小时前
SAP MM 供应商银行主数据更新报错!message R1228!
android·java·服务器
一笑的小酒馆18 小时前
Android智能猫砂盆视频加载慢卡顿问题分析
android