Android LiveData:当从后台重新打开应用程序时,如何避免从数据库传输数据?

问题描述 投票:0回答:1

我的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方法。但是,在这种情况下,我的所有数据都从数据库中重新读取,这将消耗数据带宽。

我的问题是:

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

谢谢

android firebase firebase-realtime-database android-livedata
1个回答
1
投票

您需要做的是在LiveData上设置各种“超时”,以使其在您认为适当的延迟时间内保持不活动状态。

我正是在这种情况下实现了“ LingeringLiveData”超类。您可以在GitHub上的我的项目中看到它。它是用Kotlin编写的,但是您应该可以轻松地将其移植到Java。

子类需要提供startLingeringstopLingering的实现,以反映您通常在onActiveonInactive中所做的工作。

[基本上,它设置了一个计时器,以在调用endLingering之后延迟对onInactive的调用,但前提是该时间到期之前没有调用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 convenience constructor,它接受类似的超时参数并在协程中运行代码。您将无法从Java完全使用它,但是很高兴知道。


0
投票

在这种情况下,减少数据下载的最简单方法是在Firebase客户端中将其下载到enable disk persistence

启用磁盘持久性后,Firebase客户端会将从服务器获取的所有数据写入本地磁盘缓存,如果缓存太大,则会清除较旧的数据。

当客户端重新启动时,客户端将首先从磁盘读取数据,然后仅使用所谓的增量同步从服务器请求更新。尽管此增量同步仍在传输数据,但通常应大大少于您收听的位置的总数据。

© www.soinside.com 2019 - 2024. All rights reserved.