MVVM - 在应用程序关闭时从通知开始访问 BroadcastReceiver 中的 ViewModel/SQLite

MVVM - Accessing ViewModel/SQLite in a BroadcastReceiver started from a notification when app is closed

我有一个每隔几天发送的提醒通知。

该通知的发送是通过重复 AlarmManager 触发的。通知本身内置于我的 BroadcastReceiveronReceive 中(如 所述)。所以当onReceive被触发时,app连open/running.

现在 我想访问我的(本地)SQLite 数据库 并获取正确的内容来构建通知,但我如何获得 ViewModelProvider(代码中的 xxx)在这个地方甚至可以访问我的 ViewModel?

public void onReceive(Context context, Intent intent) {    

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

    //do stuff
}

或者问一个更好的问题,这是好的做法吗?
另一种可能性是将触发 onReceivePendingIntent 中的所有内容都填满,这样我就可以在收到后一个一个地检索它。但这会更难,因为它是一个重复的警报,每次都需要不同的内容,但只触发一次。


我查看了一些搜索结果,但它们没有解决我的问题:


编辑:

正在阅读LiveData beyond the 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 的真正目的是什么?
它会将您的数据转换为某种 view-convenient 格式吗?
它会处理数据更新吗? (我的意思是,会不会有数据更新?好像你有一段时间有一个通知)
或者它只会让干净的同步代码变得杂乱无章,并使其变得毫无意义?

如果你只对最后一个问题回答 'yes',你可能不需要这里的 ViewModel:) 您需要其他架构吗?不,你不需要架构。您需要显示一个通知,那就去做吧!


如果你是真正的MVVM粉丝,你还是可以通过的。
首先,删除 ViewModelProviders.of 因为它不可能在这里使用。它需要 activity 或片段,而你两者都没有。 ViewModelProvider 的目的是在重新创建 activity/fragment 时为您提供相同的视图模型实例 - 这显然不是您的情况。
其次,自己构建viewmodel:new NotificationViewModel().
第三,return 来自您的视图模型的普通对象而不是实时数据,因为您的数据不是实时的。

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

请注意,您甚至不需要扩展 ViewModel class,因为您不使用 ViewModelProviders。

如果问题是读取 SQLite 数据库,则不需要 ViewModel。问题可能是无法直接调用挂起函数 (viewmodelscope.launch{}),但有一个简单的解决方法:runBlocking。

我假设 Broadcastreceiver 已经在后台,所以不需要启动后台协程。

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