实现一个不完美的Android Activity Results API,但是比官方使用起来方便。

142 阅读1分钟

写这篇文章起因:juejin.cn/post/708159… image.png

先看一下官方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
    }
}