startActivityForResult废弃了,用Activity Result API吧

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

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

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

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

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

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        findViewById<Button>(R.id.btn1).setOnClickListener {
            val intent = Intent(this, SecondActivity::class.java)
            val  bundle=Bundle()
            bundle.putString("key","from MainActivity data")
            intent.putExtras(bundle)
            startActivityForResult(intent, 1)
        }

    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        when (requestCode) {
            1 ->
                if (resultCode == RESULT_OK) {
                    val stringExtra = data?.getStringExtra("data")
                    Log.e("TAG", "onActivityResult: $stringExtra")
                }
        }
    }
}

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

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

class SecondActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_second)
        val extras = intent.extras
        val data = extras?.getString("key")
        Log.e("SecondActivity", "onCreate: $data" )
        findViewById<Button>(R.id.btn).setOnClickListener {
            val intent = Intent()
            intent.putExtra("data", "data from SecondActivity")
            setResult(RESULT_OK, intent)
            finish()
        }
    }
}

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

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

SecondActivity: onCreate: from MainActivity data

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

TAG: onActivityResult: data from SecondActivity

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

import androidx.activity.result.contract.ActivityResultContracts

class MainActivity : AppCompatActivity() {

    private val requestDataLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
        if (result.resultCode == RESULT_OK) {
            val data = result.data?.getStringExtra("data")
            Log.e("TAG", "registerForActivityResult: $data")
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        findViewById<Button>(R.id.btn1).setOnClickListener {
            val intent = Intent(this, SecondActivity::class.java)
            val bundle = Bundle()
            bundle.putString("key", "from MainActivity data")
            intent.putExtras(bundle)
            requestDataLauncher.launch(intent)
           // startActivityForResult(intent, 1)
        }

    }
}

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

  @NonNull
    @Override
    public final <I, O> ActivityResultLauncher<I> registerForActivityResult(
            @NonNull ActivityResultContract<I, O> contract,
            @NonNull ActivityResultCallback<O> callback) {
        return registerForActivityResult(contract, mActivityResultRegistry, callback);
    }

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

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

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

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

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

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        findViewById<Button>(R.id.btn1).setOnClickListener {
            val intent = Intent(this, SecondActivity::class.java)
            val bundle = Bundle()
            bundle.putString("key", "from MainActivity data1")
            intent.putExtras(bundle)
            startActivityForResult(intent, 1)
        }
        findViewById<Button>(R.id.btn2).setOnClickListener {
            val intent = Intent(this, ThreeActivity::class.java)
            val bundle = Bundle()
            bundle.putString("key", "from MainActivity data2")
            intent.putExtras(bundle)
            startActivityForResult(intent, 2)
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        when (requestCode) {
            1 -> {
                if (resultCode == RESULT_OK) {
                    val stringExtra = data?.getStringExtra("data")
                    Log.e("TAG", "onActivityResult: 1$stringExtra")
                }
            }
            2 ->
                if (resultCode == RESULT_OK) {
                    val stringExtra = data?.getStringExtra("data")
                    Log.e("TAG", "onActivityResult: 2 $stringExtra")
                }
        }
    }
}

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

class MainActivity : AppCompatActivity() {

    private val requestDataOneLauncher =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
            if (result.resultCode == RESULT_OK) {
                val data = result.data?.getStringExtra("data")
                Log.e("TAG", "registerForActivityResult:one  $data")
            }
        }
    private val requestDataTwoLauncher =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
            if (result.resultCode == RESULT_OK) {
                val data = result.data?.getStringExtra("data")
                Log.e("TAG", "registerForActivityResult:two  $data")
            }
        }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        findViewById<Button>(R.id.btn1).setOnClickListener {
            val intent = Intent(this, SecondActivity::class.java)
            val bundle = Bundle()
            bundle.putString("key", "from MainActivity data1")
            intent.putExtras(bundle)
            requestDataOneLauncher.launch(intent)
          
        }
        findViewById<Button>(R.id.btn2).setOnClickListener {
            val intent = Intent(this, SecondActivity::class.java)
            val bundle = Bundle()
            bundle.putString("key", "from MainActivity data2")
            intent.putExtras(bundle)
            requestDataTwoLauncher.launch(intent)

        }
    }
}

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

  • 8
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Chen_ShengJie

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

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

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

打赏作者

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

抵扣说明:

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

余额充值