MVVM — доступ к ViewModel/SQLite в BroadcastReceiver начался с уведомления при закрытии приложения

У меня есть уведомление-напоминание, которое отправляется каждые несколько дней.

Отправка этого уведомления запускается повторяющимся AlarmManager. Само уведомление встроено в onReceive моего BroadcastReceiver (как описано здесь). Поэтому, когда срабатывает onReceive, приложение даже не открывается/не работает.

Теперь в этот момент Я хочу получить доступ к своей (локальной) базе данных SQLite и получите правильный контент для создания уведомления, но как мне получить ViewModelProvider (xxx в коде) в этом месте, чтобы даже получить доступ к моему ViewModel?

public void onReceive(Context context, Intent intent) {    

    NotificationViewModel viewModel = 
    ViewModelProviders.of(XXX).get(NotificationViewModel.class);

    //do stuff
}

Или, если лучше задать вопрос, это вообще хорошая практика?
Другой возможностью было бы заполнение всего контента в PendingIntent, который вызовет onReceive, чтобы я мог получать его один за другим после получения. Но это было бы еще сложнее, так как это повторяющийся будильник, и каждый раз требуется разное содержимое, но он срабатывает только один раз.


Я просмотрел несколько результатов поиска, но они не решили мою проблему:

  • Архитектура MVVM для пользовательских представлений на Android
    -> Кажется, что много кода для такой незначительной проблемы, плюс это Kotlin, что мне трудно понять
  • Работа с BroadcastReceivers с использованием шаблона проектирования Model View Presenter
    -> Здесь кажется, что сначала необходимо настроить несколько вещей в действиях, прежде чем даже можно будет их использовать, но мне нужно запустить этот код без запуска моего приложения.
  • Доступ к BroadCastReceiver в ViewModel
    -> Это кажется наиболее близким к тому, что мне нужно, но он также требует предварительной настройки. Я хотел попробовать это, но мне нужно было бы вручную создать мою MainActivity, чтобы получить доступ к ее переменным таким образом. Разве это не откроет новую активность на устройстве пользователя без предупреждения?
    Можно ли вообще получить доступ к моей базе данных без моего приложения на переднем плане?

Редактировать:

Читая LiveData за пределами ViewModel [...], говорится

If part of your app doesn’t affect the UI, you probably don’t need LiveData.

Это означает, что я должен просто получить доступ к моему репозиторию с контекстом и получить из него необработанные данные, без оболочки LiveData?

Так

public void onReceive(Context context, Intent intent) {

    NotificationRepository rp = new NotificationRepository(context);
    MessageNotification notification = rp.getNextNotification();
}

вместо

public void onReceive(Context context, Intent intent) {

    NotificationViewModel viewModel = 
    ViewModelProviders.of(XXX).get(NotificationViewModel.class);
    MessageNotification notification = 
    viewModel.getNextNotification().observe(XXX, new 
         Observer<MessageNotification>() {
            @Override
            public void onChanged(MessageNotification messageNotification) {
                //do stuff
            }
         });
}

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

5
0
2 943
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Какова реальная цель ViewModel в этой ситуации? Преобразует ли он ваши данные в удобный для просмотра формат?
Будет ли он обрабатывать обновления данных? (Я имею в виду, будут ли когда-нибудь обновления данных? Кажется, вы получаете одно уведомление через некоторое время)
Или он просто загромождает чистый синхронный код и делает его асинхронным без какой-либо реальной цели?

Если вы ответили «да» только на последний вопрос, вам, вероятно, ViewModel здесь не нужен :) Вам нужна другая архитектура? Нет, вам не нужна архитектура. Вам нужно отобразить уведомление, так что просто сделайте это!


Если вы настоящий фанат MVVM, вы все равно можете пройти.
Во-первых, бросьте ViewModelProviders.of, потому что его здесь нельзя использовать. Это требует активности или фрагмента, и у вас нет ни того, ни другого. Целью ViewModelProvider является предоставление вам одного и того же экземпляра модели представления при воссоздании активности/фрагмента — это явно НЕ ваш случай. Во-вторых, создайте модель представления самостоятельно: new NotificationViewModel().
В-третьих, верните обычный объект из вашей модели представления вместо живых данных, потому что ваши данные не работают.

public class NotificationViewModel {
    MessageNotification getNextNotification() {
        // ...
    }
}

Обратите внимание, что вам даже не нужно расширять класс ViewModel, потому что вы не используете ViewModelProviders.

Да, это в основном то, что я сделал, просто использовал AsynTask, чтобы получить данные из репозитория самостоятельно, без вещей ViewModel и LiveData, поскольку в этом случае это действительно не добавляет никакой ценности.

Big_Chair 19.05.2019 10:54

Если проблема заключается в чтении базы данных SQLite, ViewModel не требуется. Проблема может заключаться в том, что функции приостановки нельзя вызывать напрямую (viewmodelscope.launch{}), но есть простое решение: runBlocking.

Я предполагаю, что Broadcastreceiver уже находится в фоновом режиме, поэтому нет необходимости запускать фоновую сопрограмму.

runBlocking {
   val reminders = favoriteDao.queryAllReminders()
   reminders.forEach { reminder ->
       Log.i("Reminder", reminder.info)
   }
}

Другие вопросы по теме