作者AS版本:Android Studio 2021.2.1稳定版:代号“花栗鼠”

image-20220805113558620

实验时间:2022/08/07

一,背景

在郭霖老师的《第一行代码》3.3.5小结中,演示使用 Intent 向上返回数据的时候使用的是 startActivityForResult,但是当你使用的时候却提示说:image-20220807210503808

来到官网一看:image-20220807210627550

好家伙,这 Google 的 Android 技术迭代也太快了吧,《第一行代码》第三版是用 Kotlin 写的,这出来才多久就好多地方被”迭代“了,哈哈哈哈。好吧,那我们就一起来探究探究这个 ActivityResult API

二,总体介绍

Activity Result API 会提供 registerForActivityResult()API,用于注册结果回调。registerForActivityResult() 接受 ActivityResultContractActivityResultCallback 作为参数,并返回 ActivityResultLauncher,供您用来启动另一个 activity。

ActivityResultContract 定义ActivityResultLauncher.launch调用时需要传入的参数类型以及回调ActivityResultCallback返回类型。这些 API 可为拍照和请求权限等基本 intent 操作提供默认协定,当然我们也可以自己重写。

ActivityResultCallback 是单一方法接口,只有 onActivityResult()一个抽象方法(所以这里可以用 Lambda表达式),可接受 ActivityResultContract 中定义的输出类型的对象:

1
2
3
4
//参数     ActivityResultContract  ActivityResultCallback
//返回值 ActivityResultLauncher
val activityResultLauncher = registerForActivityResult(activityResultContract, activityResultCallback)
//这里是方便大家逻辑理解,其实后面那个都是写成 Lambda

如果您有多个使用不同协定或需要单独回调的 activity 结果调用,则可以多次调用 registerForActivityResult(),以注册多个 ActivityResultLauncher 实例。

!!!注意!!!:您必须在创建 fragment 或 activity 之前调用 registerForActivityResult();在 fragment 或 activity 的 Lifecycle 达到 CREATED 之前,您将无法启动 ActivityResultLauncher

这条注意非常重要!给我细品!!!也就是说 registerForActivityResult()必须写在 onCreate方法外面,这是一个容易犯错的坑。

三,代码演示

registerForActivityResult() 只是注册了回调,它并不会自动给你启动另一个 activity 并发出结果请求。这些操作由返回的 ActivityResultLauncher 实例负责。

调用 launch() 会启动生成结果的过程。当用户完成后续 activity 并返回时,系统将执行 ActivityResultCallback 中的 onActivityResult()。我们常见的做法就是直接在registerForActivityResult()的后边直接用 Lambda 实现,具体一会看演示。

  1. FirstActivity 中:

    如果还用 startActivityForResult:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.first_layout)

    button03.setOnClickListener {
    startActivityForResult(Intent(this, SecondActivity::class.java), 1)
    }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    when (requestCode) {
    1 -> if (resultCode == RESULT_OK) {
    val returnedData = data?.getStringExtra("data_return")
    Log.d("FirstActivity", "returned data is $returnedData")
    }
    }
    }
    }

    实现同样效果的 registerForActivityResult:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    class MainActivity : AppCompatActivity() {

    val activityResultLauncher =
    registerForActivityResult(ActivityResultContracts.StartActivityForResult()
    ) { result ->
    if ( result.resultCode == RESULT_OK) {
    val returnData = result.data?.getStringExtra("data_return")
    Log.d( "FirstActivity", "returned data is $returnData" )
    }
    }

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

    button03.setOnClickListener {
    activityResultLauncher.launch(Intent(this, SecondActivity::class.java))
    }

    }
    }
  2. SecondActivity 中 onCreate 中 :

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    //点这个按钮给 Activity1 传递数据
    button2_2.setOnClickListener {
    val intent = Intent()
    intent.putExtra("data_return", "Hello FirstActivity")
    setResult(RESULT_OK, intent)
    finish()
    /**
    * 可以看到,我们还是构建了一个Intent,只不过这个Intent仅仅用于传递数据而已,它没有指定任何的“意图”。紧接着把要传递的数据存放在Intent中,然后调用了setResult()方法。这个方法非常重要,专门用于向上一个Activity返回数据。setResult()方法接收两个参数:第一个参数用于向上一个Activity返回处理结果,一般只使用RESULT_OK或RESULT_CANCELED这两个值;第二个参数则把带有数据的Intent传递回去。最后调用了finish()方法来销毁当前Activity
    */
    }
    //设置通过 Back 键也会返回数据
    override fun onBackPressed() {
    val intent = Intent()
    intent.putExtra("data_return", "Hello FirstActivity")
    setResult(RESULT_OK, intent)
    finish()
    }

    QQ图片20220730180111

参考资料:

  1. https://developer.android.google.cn/training/basics/intents/result?hl=zh-cn
  2. https://blog.csdn.net/dragon_fly_along/article/details/119816798