很多开发者对onActivityResult抱怨已久:需要定义resultCoderequestCode,使用繁琐且容易出错。现在通过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"  orimplementation "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))        }    }}

省掉了烦人的resultCoderequestCode,代码更优雅

其他场景


看几个常见场景中如何使用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

更多相关文章

  1. 一款常用的 Squid 日志分析工具
  2. GitHub 标星 8K+!一款开源替代 ls 的工具你值得拥有!
  3. RHEL 6 下 DHCP+TFTP+FTP+PXE+Kickstart 实现无人值守安装
  4. Linux 环境下实战 Rsync 备份工具及配置 rsync+inotify 实时同步
  5. 用Preferences,通过xml文件跳转到另一个Activity
  6. Android(安卓)Mediascanner实现机制
  7. Android(安卓)Logcat 报错:Could not create the view: For input
  8. Android原生工程配置导入uni-app项目-混合开发
  9. android 如何调用WPS显示工作文件

随机推荐

  1. 运行android的SDK Manager.exe无反应
  2. google android 项目
  3. Android矢量图(三)--VectorDrawable渐变
  4. 手机玩转局域网利器dsploit(csploit)
  5. 2010.12.28(4)——— android tab 过多的
  6. Android基础--------Android常用控件介绍
  7. Android短信发送流程之普通短信发送(原)
  8. Android用RecyclerView实现动态添加本地
  9. android页面间传输数据
  10. Android的线程使用来更新UI------Thread