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. Однако в этом случае все мои данные перечитываются из базы данных, которая будет использовать пропускную способность данных.

Мой вопрос:

Каков наилучший способ избежать повторного чтения данных каждый раз, когда приложение возвращается из фона?

Благодарность

Всего 2 ответа


То, что вам нужно будет сделать, это установить своего рода «тайм-аут» в своих LiveData, чтобы он не стал становиться неактивным на столько времени, сколько вы считаете нужным.

Я реализовал суперкласс " LingeringLiveData " именно для этой ситуации. Вы можете увидеть это в моем проекте на GitHub. Он написан на Kotlin, но вы сможете без проблем перенести его на Java.

Подклассы должны предоставлять реализации для startLingering и stopLingering которые отражают то, что вы обычно делаете в onActive и onInactive .

По сути, он устанавливает таймер для задержки вызова 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, который принимает аналогичный параметр времени ожидания и выполняет код в сопрограмме. Вы не сможете использовать вообще с Java, но это приятно знать.


Самый простой способ уменьшить загрузку данных в этом случае - включить сохранение диска в клиенте Firebase.

С включенным постоянством диска клиент Firebase будет записывать любые данные, которые он получает с сервера, в локальный дисковый кеш, очищая старые данные, если кеш становится слишком большим.

Когда клиент перезапускается, клиент сначала считывает данные с диска, а затем запрашивает только обновления с сервера, используя так называемую дельта-синхронизацию. Хотя эта дельта-синхронизация по-прежнему передает данные, она, как правило, должна быть значительно меньше общих данных в месте, которое вы прослушиваете.


Есть идеи?

10000