首页 > 解决方案 > Android LiveData:如何避免从后台重新打开应用程序时从数据库传输数据?

问题描述

我的 Android 应用正在监听 Firebase 数据库。每当我的活动变为非活动状态时,我会停止监听器,当活动再次变为活动状态时,我会重新开始监听。这是使用 LiveData 和 'onActive' 和 'onInactive' 方法完成的,如下所示:

@Override
protected void onActive() {
    Log.d(LOG_TAG, "onActive");
    query.addValueEventListener(listener);
}

@Override
protected void onInactive() {
    Log.d(LOG_TAG, "onInactive");
    query.removeEventListener(listener);
}

使用调试器,我注意到当我按下后退按钮并关闭应用程序时,onInactive 方法被调用,应用程序进入后台。当我重新打开应用程序时,通过在后台应用程序中选择它,调用 onActive 方法。但是,在这种情况下,我的所有数据都是从数据库中重新读取的,这将消耗数据带宽。

我的问题是:

每次应用程序从后台返回时,避免重新读取数据的最佳方法是什么?

谢谢

标签: androidfirebasefirebase-realtime-databaseandroid-livedata

解决方案


你需要做的是在你的 LiveData 上设置一个“超时”,以便它在你认为合适的延迟时间内延迟变为非活动状态。

我为这种情况实现了一个“ LingeringLiveData ”超类。你可以在我在 GitHub 上的一个项目中看到它。它是用 Kotlin 编写的,但您应该能够毫不费力地将其移植到 Java。

子类需要提供 和 的实现startLingeringstopLingering这反映了您通常在onActive和中所做的事情onInactive

基本上,它会设置一个计时器来延迟对endLingeringafteronInactive的调用,但前提onActive是在该时间到期之前未调用。这使您可以在不丢失侦听器的情况下停止和启动应用程序。

abstract class LingeringLiveData<T> : LiveData<T>() {

    companion object {
        private const val STOP_LISTENING_DELAY = 2000L
    }

    // To be fully unit-testable, this code should use an abstraction for
    // future work scheduling rather than Handler itself.
    private val handler = Handler()

    private var stopLingeringPending = false
    private val stopLingeringRunnable = StopLingeringRunnable()

    /**
     * Called during onActive, but only if it was not previously in a
     * "lingering" state.
     */
    abstract fun beginLingering()

    /**
     * Called two seconds after onInactive, but only if onActive is not
     * called during that time.
     */
    abstract fun endLingering()

    @CallSuper
    override fun onActive() {
        if (stopLingeringPending) {
            handler.removeCallbacks(stopLingeringRunnable)
        }
        else {
            beginLingering()
        }
        stopLingeringPending = false
    }

    @CallSuper
    override fun onInactive() {
        handler.postDelayed(stopLingeringRunnable, STOP_LISTENING_DELAY)
        stopLingeringPending = true
    }

    private inner class StopLingeringRunnable : Runnable {
        override fun run() {
            if (stopLingeringPending) {
                stopLingeringPending = false
                endLingering()
            }
        }
    }

}

Jetpack LiveData KTX 现在还提供了一个liveData 便利构造函数,它接受类似的超时参数并在协程中运行代码。您将无法从 Java 中使用,但很高兴知道这一点。


推荐阅读