写这篇文章起因:juejin.cn/post/708159…
先看一下官方Activity Results API
首先注册:
private val startForResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result: ActivityResult ->
when (result.resultCode) {
RESULT_OK -> {
// do something
}
RESULT_CANCELED -> {
finish()
}
}
}
用的时候
btn.setOnClickListener {
startForResult.launch(Intent(this@MainActivity, SecondActivity::class.java)
}
大家自己实现的Activity Result无非就是这样
btn.setOnClickListener {
forActivityResult(Intent(this@MainActivity, SecondActivity::class.java)) {
// do something
}
}
为什么我说大家实现的这种方式不完美呢?
因为有时候Activity会被回收,比如旋转屏幕或者长时间在后台等原因。
当SecondActivity返回MainActivity的时候,由于MainActivity的回收重建,
所以咱们自己实现的方案铁定是拿不到回调了。
好了!
下面贴一下我的实现方案,作为抛砖引玉吧。想必大家目前已经有了各式各样的实现方式了。
实现一个扩展方法:
fun LifecycleOwner.startActivityForBack(startActivity: () -> Unit, callBack: () -> Unit) {
this.lifecycle.addObserver(object : LifecycleBoundObserver(this) {
override fun onActive() {
lifecycle.removeObserver(this)
callBack()
}
override fun onInactive() {
// no-op
}
})
startActivity()
}
用法:
btn.setOnClickListener {
startActivityForBack({
Router.jumpToSecondActivity()
}, {
// do something
})
}
贴上LifecycleBoundObserver源代码:
abstract class LifecycleBoundObserver(private val owner: LifecycleOwner) : LifecycleEventObserver {
private var active = isActiveState(owner.lifecycle.currentState)
private var activeCount: Int = if (active) 1 else 0
private fun isActiveState(state: Lifecycle.State): Boolean = state.isAtLeast(Lifecycle.State.RESUMED)
abstract fun onActive()
abstract fun onInactive()
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
if (source.lifecycle.currentState == Lifecycle.State.DESTROYED) {
owner.lifecycle.removeObserver(this)
return
}
activeStateChanged(isActiveState(source.lifecycle.currentState))
}
private fun activeStateChanged(active: Boolean) {
if (active == this.active) {
return
}
this.active = active
val wasInactive = activeCount == 0
activeCount += if (active) 1 else -1
if (wasInactive && active) {
onActive()
}
if (activeCount == 0 && !active) {
onInactive()
}
}
}
加一些常用的扩展方法:
fun LifecycleOwner.login(callBack: () -> Unit = {}) {
startActivityForBack({ Router.jumpToLogin() }, callBack)
}
用法:
btn.setOnClickListener {
login {
// do something
}
}
结束~~~~
对了,等有时间写一篇关于DialogFragment Results API实现方法。
跟Activity Results API是一模一样的。
首先注册:
val dialogLauncher = registerForDialogResult(DialogCommonResultContract(),
DefaultDialogResultCallback(result = { _: DialogInterface?, result: Any? ->
// do something
}))
用的时候:
btn.setOnClickListener {
dialogLauncher.launch(CustomDialogFragment())
}
解决的也是因为Activity销毁重建后,Dialog弹窗接收不到回调的问题。如:
btn.setOnClickListener {
CustomDialogFragment.showDialog(activity) {
// do something
}
}