• startActivityForResult废弃了,用Activity Result API吧


    因为项目中突然需要用到两个activity之间进行数据交互,脑子里第一想法就是用EventBus来实现,但是需求仅仅只有2个activity之间进行交互(神奇的需求?),所以考虑几百年前用过的startActivityForResult来实现,但撸代码的时候发现,它过时了!!!

     如果你将项目中的appcompat库升级到1.3.0或更高的版本,startActivityForResult()方法就已经显示被废弃了,因为项目中引入的就是1.3.0的

    所以才发现过时的,如果版本低了,我还蒙在鼓里。

         废弃了,自然有替代品。新欢胜旧爱,官网建议用Activity Result API来取代startActivityForResult了。

       OK,先回顾下startActivityForResult的用法,它主要作用就是用于两个activity之间传递数据,例如:

    1. class MainActivity : AppCompatActivity() {
    2. override fun onCreate(savedInstanceState: Bundle?) {
    3. super.onCreate(savedInstanceState)
    4. setContentView(R.layout.activity_main)
    5. findViewById
    6. val intent = Intent(this, SecondActivity::class.java)
    7. val bundle=Bundle()
    8. bundle.putString("key","from MainActivity data")
    9. intent.putExtras(bundle)
    10. startActivityForResult(intent, 1)
    11. }
    12. }
    13. override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    14. super.onActivityResult(requestCode, resultCode, data)
    15. when (requestCode) {
    16. 1 ->
    17. if (resultCode == RESULT_OK) {
    18. val stringExtra = data?.getStringExtra("data")
    19. Log.e("TAG", "onActivityResult: $stringExtra")
    20. }
    21. }
    22. }
    23. }

    在MainActivity里通过点击一个按钮,往Bundle里添加数据,然后放到intent里,通过startActivityForResult向SecondActivity传递数据,并且重写了onActivityResult()方法去解析SecondActivity返回来的数据。

    SecondActivity就稍微简单点了,先获取到MainActivity传递过来的数据,然后再点击一个按钮,发送新的数据返回给MainActivity。

    1. class SecondActivity : AppCompatActivity() {
    2. override fun onCreate(savedInstanceState: Bundle?) {
    3. super.onCreate(savedInstanceState)
    4. setContentView(R.layout.activity_second)
    5. val extras = intent.extras
    6. val data = extras?.getString("key")
    7. Log.e("SecondActivity", "onCreate: $data" )
    8. findViewById
    9. val intent = Intent()
    10. intent.putExtra("data", "data from SecondActivity")
    11. setResult(RESULT_OK, intent)
    12. finish()
    13. }
    14. }
    15. }

    以上代码应该没毛病,早几年每个项目百分百会用到的.

    结果显而易见,从MainActivity点击按钮跳转到SecondActivity界面会打印 

    SecondActivity: onCreate: from MainActivity data

    然后在SecondActivity点击按钮回到MainActivity打印

    TAG: onActivityResult: data from SecondActivity

    接着我们学习一下如何使用Activity Result API来实现同样的功能。

    1. import androidx.activity.result.contract.ActivityResultContracts
    2. class MainActivity : AppCompatActivity() {
    3. private val requestDataLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
    4. if (result.resultCode == RESULT_OK) {
    5. val data = result.data?.getStringExtra("data")
    6. Log.e("TAG", "registerForActivityResult: $data")
    7. }
    8. }
    9. override fun onCreate(savedInstanceState: Bundle?) {
    10. super.onCreate(savedInstanceState)
    11. setContentView(R.layout.activity_main)
    12. findViewById
    13. val intent = Intent(this, SecondActivity::class.java)
    14. val bundle = Bundle()
    15. bundle.putString("key", "from MainActivity data")
    16. intent.putExtras(bundle)
    17. requestDataLauncher.launch(intent)
    18. // startActivityForResult(intent, 1)
    19. }
    20. }
    21. }

    SecondActivity完全不用动,代码不用变。主要看下MainActivity的代码改动,移除了对onActivityResult()方法的重写,而是调用registerForActivityResult()方法来注册一个对Activity结果的监听。registerForActivityResult()方法接收两个参数,第一个参数是一种Contract类型,由于我们是希望从另外一个Activity中请求数据,因此这里使用了StartActivityForResult这种Contract。第二个参数是一个Lambda表达式,当有结果返回时则会回调到这里,然后我们在这里获取并处理数据即可。

    1. @NonNull
    2. @Override
    3. public final ActivityResultLauncher registerForActivityResult(
    4. @NonNull ActivityResultContract contract,
    5. @NonNull ActivityResultCallback callback) {
    6. return registerForActivityResult(contract, mActivityResultRegistry, callback);
    7. }

    从源码可以看到registerForActivityResult返回的是ActivityResultLauncher对象,

     可以看到该对象当中有launch()方法可以用于去启用Intent。所以我们的代码中就能使用

     requestDataLauncher.launch(intent)去进行调整,从而代替startActivityForResult()方法。

    以上代码运行效果和startActivityForResult()的完全一致。如果说单纯从数据跳转传递来讲,这也差不多呀。没啥优势的。

    再来个例子,多任务之间进行区分。

    1. class MainActivity : AppCompatActivity() {
    2. override fun onCreate(savedInstanceState: Bundle?) {
    3. super.onCreate(savedInstanceState)
    4. setContentView(R.layout.activity_main)
    5. findViewById
    6. val intent = Intent(this, SecondActivity::class.java)
    7. val bundle = Bundle()
    8. bundle.putString("key", "from MainActivity data1")
    9. intent.putExtras(bundle)
    10. startActivityForResult(intent, 1)
    11. }
    12. findViewById
    13. val intent = Intent(this, ThreeActivity::class.java)
    14. val bundle = Bundle()
    15. bundle.putString("key", "from MainActivity data2")
    16. intent.putExtras(bundle)
    17. startActivityForResult(intent, 2)
    18. }
    19. }
    20. override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    21. super.onActivityResult(requestCode, resultCode, data)
    22. when (requestCode) {
    23. 1 -> {
    24. if (resultCode == RESULT_OK) {
    25. val stringExtra = data?.getStringExtra("data")
    26. Log.e("TAG", "onActivityResult: 1$stringExtra")
    27. }
    28. }
    29. 2 ->
    30. if (resultCode == RESULT_OK) {
    31. val stringExtra = data?.getStringExtra("data")
    32. Log.e("TAG", "onActivityResult: 2 $stringExtra")
    33. }
    34. }
    35. }
    36. }

    通过设置不同的requestCode值来区分传递不同界面的数据。因此获取返回的数据时也要在onActivityResult()方法当中,再对requestCode进行判断。这种传统的写法,大家应该都很熟悉,也见得多了,那么看下Activity Result API是怎么实现这种多任务的数据传递接收的

    1. class MainActivity : AppCompatActivity() {
    2. private val requestDataOneLauncher =
    3. registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
    4. if (result.resultCode == RESULT_OK) {
    5. val data = result.data?.getStringExtra("data")
    6. Log.e("TAG", "registerForActivityResult:one $data")
    7. }
    8. }
    9. private val requestDataTwoLauncher =
    10. registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
    11. if (result.resultCode == RESULT_OK) {
    12. val data = result.data?.getStringExtra("data")
    13. Log.e("TAG", "registerForActivityResult:two $data")
    14. }
    15. }
    16. override fun onCreate(savedInstanceState: Bundle?) {
    17. super.onCreate(savedInstanceState)
    18. setContentView(R.layout.activity_main)
    19. findViewById
    20. val intent = Intent(this, SecondActivity::class.java)
    21. val bundle = Bundle()
    22. bundle.putString("key", "from MainActivity data1")
    23. intent.putExtras(bundle)
    24. requestDataOneLauncher.launch(intent)
    25. }
    26. findViewById
    27. val intent = Intent(this, SecondActivity::class.java)
    28. val bundle = Bundle()
    29. bundle.putString("key", "from MainActivity data2")
    30. intent.putExtras(bundle)
    31. requestDataTwoLauncher.launch(intent)
    32. }
    33. }
    34. }

    通过ActivityResultLauncher不同对象处理不同的任务数据,无需借助requestCode数字来判断,万一数字多了不对,还容易出错。所以Activity Result API存在是有一定的合理性的。

  • 相关阅读:
    零基础自学javase黑马课程第十四天
    Mybatis保存时参数携带了逗号和空格导致SQL保存异常
    僵尸网络|让人防不胜防的内部网络安全问题,作为企业IT不得不了解的基础安全
    java-php-net-python-个人信息管理系统计算机毕业设计程序
    Vue.js+SpringBoot开发计算机机房作业管理系统
    【电控笔记5.4】pwm延迟
    树和森林知识
    Abp6.0 使用 appsettings.json配置Serilog.Sinks.MariaDB
    【Java】解决安全漏洞
    SpringBoot自定义注解
  • 原文地址:https://blog.csdn.net/csj731742019/article/details/126670794