У меня есть уведомление-напоминание, которое отправляется каждые несколько дней.
Отправка этого уведомления запускается повторяющимся 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, чтобы я мог получать его один за другим после получения. Но это было бы еще сложнее, так как это повторяющийся будильник, и каждый раз требуется разное содержимое, но он срабатывает только один раз.
Я просмотрел несколько результатов поиска, но они не решили мою проблему:
Читая 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?
Должен ли я использовать какую-то другую архитектуру? Прямо сейчас мне кажется, что это имеет смысл, так как это то, что я получаю только один раз, и мне не нужно следить за изменениями.
Какова реальная цель ViewModel в этой ситуации?
Преобразует ли он ваши данные в удобный для просмотра формат?
Будет ли он обрабатывать обновления данных? (Я имею в виду, будут ли когда-нибудь обновления данных? Кажется, вы получаете одно уведомление через некоторое время)
Или он просто загромождает чистый синхронный код и делает его асинхронным без какой-либо реальной цели?
Если вы ответили «да» только на последний вопрос, вам, вероятно, ViewModel здесь не нужен :) Вам нужна другая архитектура? Нет, вам не нужна архитектура. Вам нужно отобразить уведомление, так что просто сделайте это!
Если вы настоящий фанат MVVM, вы все равно можете пройти.
Во-первых, бросьте ViewModelProviders.of, потому что его здесь нельзя использовать. Это требует активности или фрагмента, и у вас нет ни того, ни другого. Целью ViewModelProvider является предоставление вам одного и того же экземпляра модели представления при воссоздании активности/фрагмента — это явно НЕ ваш случай.
Во-вторых, создайте модель представления самостоятельно: new NotificationViewModel().
В-третьих, верните обычный объект из вашей модели представления вместо живых данных, потому что ваши данные не работают.
public class NotificationViewModel {
MessageNotification getNextNotification() {
// ...
}
}
Обратите внимание, что вам даже не нужно расширять класс ViewModel, потому что вы не используете ViewModelProviders.
Если проблема заключается в чтении базы данных SQLite, ViewModel не требуется. Проблема может заключаться в том, что функции приостановки нельзя вызывать напрямую (viewmodelscope.launch{}), но есть простое решение: runBlocking.
Я предполагаю, что Broadcastreceiver уже находится в фоновом режиме, поэтому нет необходимости запускать фоновую сопрограмму.
runBlocking {
val reminders = favoriteDao.queryAllReminders()
reminders.forEach { reminder ->
Log.i("Reminder", reminder.info)
}
}
Да, это в основном то, что я сделал, просто использовал AsynTask, чтобы получить данные из репозитория самостоятельно, без вещей ViewModel и LiveData, поскольку в этом случае это действительно не добавляет никакой ценности.