简化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()
相关推荐
拥小抱12 小时前
Compose 知识点
android
文章永久免费只为良心12 小时前
Web应用安全与防护_第三章_日志文件包含_从一道 CTFshow 题目讲透「日志投毒型 LFI → RCE」:原理、时序陷阱与全变种攻防手册
android·网络安全·渗透测试·漏洞危害·漏洞描述·日志投毒·红队指南
AIsoft_868913 小时前
学术讲座录音如何整理?录音APP可行吗
android·iphone
Goway_Hui15 小时前
【KMP for OpenHarmony】-- 在鸿蒙工程中使用 Apollo-Kotlin
华为·kotlin·harmonyos
Patrick在香港15 小时前
一个斜杠,把毫秒变成十几秒
android·数据库·python·性能优化·正则表达式·回溯·redos
海雅达手持终端PDA17 小时前
工业手持终端的“去手机化”演进:看海雅达如何以“同轴扫摄”终结工程妥协,重塑工业PDA新范式
android·物联网·智能手机·硬件工程·能源·制造·iot
释厄62317 小时前
AI 军备竞赛悖论——为 AI 卖游戏但 AI 需要游戏母场景
人工智能·游戏·kotlin
booboosui17 小时前
删掉一个住在本机的 agent:8 处要清,顺序不能反
android
hcgeng18 小时前
Android获取崩溃日志
android