Jetpack Compose中的startActivityForResult的正确姿势

之前在 Jetpack Compose中的导航路由 里简单的提到了从 Compose 导航到其他 Activity 页面的方式,对于不带返回结果的则就是跟以前一样简单的启动Activity的代码,而如果是startActivityForResult方式的,需要使用带回调的方式去启动,那么在以前,我们要么是使用三方库,要么是自己封装一个简单的库来使用 (至于背后原理也不是什么新鲜事了) 。

后来研究了一下,在ComposestartActivityForResult也有了新的姿势,要理解ComposestartActivityForResult的姿势,这还得从androidxstartActivityForResult的姿势说起,因为Compose 就是在androidx的基础上利用其API简单封装了一下而已。

倒也不是说以前的不能用了,毕竟有系统自带的,谁还去用第三方的呀,用第三方的还得导入一个依赖库不是,能少依赖三方的就尽量少依赖吧。

androidx之后如何正确的startActivityForResult

如何使用

如果是在ActivityFragment内部使用的话,直接调用registerForActivityResult方法即可。

例如,选择文件:

 val launcher = registerForActivityResult(ActivityResultContracts.GetContent()) {
    uri ->
     uri?.apply {
    showToast(uri.toString()) }
 }
 
 launcher.launch("image/*") 

ActivityResultContracts.GetContent()的方式获取文件launch时需要通过指定 mime type来过滤文件类型, 例如 image/* ,这会打开系统自带的一个文件选择器供你选择文件。

录制视频:

 val outVideoFile = File(externalCacheDir, "/${
     System.currentTimeMillis()}.mp4")
 val videoUri = FileProvider.getUriForFile(this, "${
     packageName}.provider", outVideoFile)
 val launcher = registerForActivityResult(ActivityResultContracts.CaptureVideo()) {
    isSuccess ->
     if (isSuccess) {
   
         showToast(outVideoFile.path)
     }
 }
 
 launcher.launch(videoUri)

拍照:

val outPictureFile = File(externalCacheDir, "/${
     System.currentTimeMillis()}.jpeg")
val pictureUri = FileProvider.getUriForFile(this, "${
     packageName}.provider", outPictureFile)
val launcher = registerForActivityResult(ActivityResultContracts.TakePicture()) {
    isSuccess ->
    if (isSuccess) {
   
        showToast(outPictureFile.path)
    }
}

launcher.launch(pictureUri)}

这两种方式需要指定Uri, 这个Uri获取有点费劲,需要先进行FileProvider配置,不过配置好就很方便了。(如果你的minSdk配置的是29,那么需要另外配置,可自行查阅相关资料,不过国内基本不会兼容这么高的版本,一般minSdk配置的会是21)

自己的内部业务Activity之间的跳转:

// MainActivity.kt 
val target = Intent(this, OtherActivity::class.java).apply {
   
    putExtra("name", "张三")
    putExtra("uid", 123)
}
val launcher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
    activityResult ->
    activityResult.data?.apply {
   
        val name = getStringExtra("name")
        name?.let {
    showToast(it) }
    }
}

launcher.launch(target)
// OtherActivity.kt
class OtherActivity: ComponentActivity() {
   
    override fun onCreate(savedInstanceState: Bundle?) {
   
        super.onCreate(savedInstanceState)
        val name = intent.getStringExtra("name") 
        val uid = intent.getIntExtra("uid", -1)
        setContent {
   
            MyComposeApplicationTheme {
   
                Surface(modifier = Modifier.fillMaxSize()) {
   
                    Column {
   
                        Text("name: $name fromCompose: $fromCompose uid: $uid", fontSize = 20.sp)
                        Button(onClick = {
   
                            val data = Intent().apply {
    putExtra("name", "小明") }
                            setResult(RESULT_OK, data)
                            finish()
                        }) {
    Text("back with result") }
                    }
                }
            }
        }
    }
}

registerForActivityResult的回调接口lambda中,仍然可以像以前那样使用activityResult.resultCode == RESULT_OK 来判断是正常返回了,还是取消操作。

在Activity/Fragment以外的类中使用:

class MyLifecycleObserver(private val registry : ActivityResultRegistry) : DefaultLifecycleObserver {
   
    lateinit var getContent : ActivityResultLauncher<String>

    override fun onCreate(owner: LifecycleOwner) {
   
        getContent = registry.register("key", owner, ActivityResultContracts.GetContent()) {
    uri ->
            // Handle the returned Uri
        }
    }

    fun selectImage() {
   
        getContent.launch("image/*")
    }
}

很简单,将代码移到一个LifecycleObserver的实现类中即可,然后在Activity/Fragment中将这个LifecycleObserver的实现类的观察者对象添加到其本身的lifecycle中即可。

class MyFragment : Fragment(
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

川峰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值