Могу ли я сделать LiveData статическим?

Не знаю, глупый ли это вопрос. Это может нарушить цель LiveData / ViewModel.

Могу ли я сделать LiveData статическим? Моя причина в том, что у меня есть слушатель из службы, который обновляет информацию. Так что мне нужен способ от сервиса «установить / изменить» LiveData.

Раньше я делал следующее, и это работает:
1. Сервис изменяет БД
2. ViewModel слушает изменение БД
3. Обновления пользовательского интерфейса в результате изменения liveData

Я обнаружил, что этот способ слишком медленный. Чтобы повысить производительность, мне нужно что-то вроде:
1. Сервис изменяет объект класса напрямую
2. ViewModel слушает изменения объекта класса
3. Обновления пользовательского интерфейса в результате изменения liveData

Чтобы достичь того, чего я хочу, мне нужно либо сделать MutableLiveData статическим, либо сделать так, чтобы класс ViewModel совместно использовал один и тот же экземпляр ViewModel между Activity.

Это хорошая идея?

public class MyViewModel extends AndroidViewModel {

    // Note: this MutableLiveData is static
    private static MutableLiveData<MyModel> mutableLiveData;

    public MyViewModel(@NonNull Application application) {
        super(application);
    }

    LiveData<MyModel> getLiveDataList() {
        if (mutableLiveData == null) {
            mutableLiveData = new MutableLiveData<>();
            loadDataFromDb();
        }
        return mutableLiveData;
    }

    private void loadDataFromDb() {
        // load data from DB
        // mutableLiveData.setValue(MyModelFromDb); // Omit the real implementation
    }

    // Note: this method is static
    public static void setData(MyModel newData) {
        mutableLiveData.setValue(newData);
    }

    @Override
    protected void onCleared() {
        super.onCleared();
    }
}

comment
Я обнаружил, что этот способ слишком медленный. Что слишком медленно? Где база данных?   -  person weston    schedule 06.03.2018
comment
Вы изучали возможность отправки локальной трансляции из вашей службы на зарегистрированный BroadcastReceiver в своей деятельности и сравнивали это время обновления с обновлениями LiveData?   -  person kandroidj    schedule 06.03.2018
comment
да, вы можете сделать его статическим, если считаете, что это будет быстрее .... но, пожалуйста, обновите базу данных из той же или другой службы ... (потому что статические данные будут жить до тех пор, пока приложение не будет на переднем плане ... при перезапуске данные будут потеряны)   -  person Santanu Sur    schedule 06.03.2018
comment
но, пожалуйста, обновите базу данных с того же самого - ›да, я планирую это сделать. Спасибо.   -  person jclova    schedule 06.03.2018
comment
Аналогичный, но более гибкий подход состоит в том, чтобы ввести уровень репозитория, который может кэшировать данные для вас: developer.android.com/topic/libraries/architecture/ Когда репозиторий создан, он может загружать данные один раз, а затем следить за БД для последующих изменений.   -  person E.M.    schedule 27.04.2018


Ответы (2)


Весь смысл ViewModel из Android Jetpack (в отличие от других версий) в том, чтобы ViewModel был осведомлен о жизненном цикле и выполнял магические действия, такие как уничтожение себя при уничтожении наблюдателя (активность / фрагмент) или сохранение изменений конфигурации (например, ориентации) без инициализируется снова и снова, что значительно упрощает решение проблем, связанных с изменениями конфигурации.

Таким образом, если вы сделаете ViewModel или LiveData статическим, вы фактически превзойдете их цель и, скорее всего, потеряете данные ViewModel, хотя необходимость в этом понятна. Таким образом, это требует, чтобы вы разработали свой способ обойти это, и первый способ, о котором вы упомянули, вероятно, лучший способ сделать это. Я не понимаю, почему у вас проблемы с первым решением. На мой взгляд, он обеспечивает лучший пользовательский опыт:

  1. Вы инициализируете ViewModel в своем фрагменте или действии в onCreate и добавляете Observer к данным.
  2. Если в базе данных уже есть какие-то данные, ваш наблюдатель получит их мгновенно, и пользовательский интерфейс будет мгновенно обновлен существующими данными.
  3. Сервис делает запрос API и изменяет БД
  4. Изменения БД запускают обновление данных в ViewModel
  5. Наблюдатель обновляет полученные данные, и вы передаете их своим представлениям / адаптерам.
  6. Пользовательский интерфейс обновляется последними данными с красивой анимацией, которая указывает на добавление / удаление элементов.

Насколько я могу судить, лучше этого быть не может. Поскольку ваш вопрос задан несколько месяцев назад, мне любопытно узнать, чем вы закончили?

person Ali Kazi    schedule 20.12.2018

  • Я думаю, что если MyViewModel будет иметь много LiveData полей, он будет расти с большим количеством геттеров и сеттеров. И что еще хуже, как для меня, вы нарушите тестируемость своего кода, потому что, если вы создадите новый экземпляр MyViewModel, вы будете ожидать, что ваши LiveData объекты не имеют состояния в этот момент времени, но поскольку это статический объект, вы не знаю, в каком именно состоянии он находится после простого создания.
  • Также нельзя переопределить статические методы. А насчет полей: если вы хотите иметь общее поле, предположим, что errorMessage, в классе A и классе B, в то время как оба они расширяют класс C (который содержит ваше общее поле), вы можете иметь неожиданное поведение. С другой стороны, вы можете дублировать этот код в других классах (что плохо).
  • Проблема с памятью: если используется большое количество статических переменных / методов. Потому что они не будут сборщиками мусора до завершения программы.

Но это только мое мнение.

person Nazarii Moshenskiy    schedule 21.12.2018