ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

ResultAPI:告别onActivityResult,拥抱ActivityResultContract

2022-01-19 13:34:26  阅读:282  来源: 互联网

标签:onCreate ResultAPI data MainActivity requestCode resultCode onActivityResult Act


很多开发者对onActivityResult抱怨已久:需要定义resultCode和requestCode,使用繁琐且容易出错。现在通过KTX新发布的ActivityResultContract可以很多好地解决上述烦恼

基本使用
Before
传统的onActivityResult写法

class MainActivity : AppCompatActivity() {

    companion object {
        private const val REQUEST_CODE = 1234
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        button_open.setOnClickListener {
            startActivityForResult(
                    SecondActivity.createIntent(this),
                    REQUEST_CODE
            )
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        Log.d("MainActivity", "requestCode: $requestCode, resultCode: $resultCode, data: $data")
    }
}


SecondActivity需要finish之前需要setResult

setResult(Activity.RESULT_OK, intent)
finish()

After
引入gradle

implementation "androidx.activity:activity-ktx:$latest_vsersion"
  or
implementation "androidx.fragment:fragment-ktx:$latest_vsersion"
class MainActivity : AppCompatActivity() {

    private val launcher: ActivityResultLauncher<Intent> =
            registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { activityResult ->
                Log.d("MainActivity", activityResult.toString())
            }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        button_open.setOnClickListener {
            launcher.launch(SecondActivity.createIntent(this))
        }
    }
}

省掉了烦人的resultCode和requestCode,代码更优雅

其他场景


看几个常见场景中如何使用ActivityResultContract:

选择文件

打开文件管理器选择图片并返回uri,首先看一下基于onActivityResult的实现:

class MainActivity : AppCompatActivity() {
    companion object {
        private const val REQUEST_CODE_CHOOSER = 1234
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        button_get_content.setOnClickListener {
            startActivityForResult(
                    Intent(Intent.ACTION_GET_CONTENT).apply {
                        addCategory(Intent.CATEGORY_OPENABLE)
                        type = "image/*"
                    },
                    REQUEST_CODE_CHOOSER
            )
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == REQUEST_CODE_CHOOSER && resultCode == Activity.RESULT_OK) {
            Log.d("MainActivity", "uri: ${data?.data}")
        }
    }
}

 基于ActivityResultContracts实现后:

class MainActivity : AppCompatActivity() {

    private val launcher = registerForActivityResult(ActivityResultContracts.GetContent()) { uri ->
        Log.d("MainActivity", "uri: $uri")
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        button_get_content.setOnClickListener {
            launcher.launch("image/*")
        }
    }
}

ActivityResultContracts.GetContent是系统预置的几种Contracts之一:

当然除以上预置的Contracts以外,也可以通过继承ActivityResultContracts自定义自己的Contracts

权限请求

requestPermission与startActivityForResult的过程比较类似:

 

//权限请求
ActivityCompat.requestPermissions(this, arrayOf(WRITE_EXTERNAL_STORAGE), REQUEST_CODE)
//返回结果
override fun onRequestPermissionsResult(
    requestCode: Int,
    permissions: Array<out String>,
    grantResults: IntArray
) {
    if (requestCode == REQUEST_CODE) {
        if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            Toast.makeText(this, "result: granted", Toast.LENGTH_LONG).show()
        }
        return
    }
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}

基于ActivityResultContract的实现:

// 设置回调
private val launcher = registerForActivityResult(RequestPermission()) {
    if (it) {
        Toast.makeText(this, "result: granted", Toast.LENGTH_LONG).show()
    }
}
// 请求权限
launcher.launch(WRITE_EXTERNAL_STORAGE)

实现原理


关于ActivityResultContract的原理比较简单,有兴趣的同学可以参考深入理解ActivityResultContracts

————————————————
版权声明:本文为CSDN博主「fundroid_方卓」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/vitaviva/article/details/107551620

标签:onCreate,ResultAPI,data,MainActivity,requestCode,resultCode,onActivityResult,Act
来源: https://blog.csdn.net/chuyouyinghe/article/details/122578739

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有