【问题标题】:MVVM - Accessing ViewModel/SQLite in a BroadcastReceiver started from a notification when app is closedMVVM - 在应用程序关闭时从通知开始访问 BroadcastReceiver 中的 ViewModel/SQLite
【发布时间】:2019-09-29 16:41:05
【问题描述】:

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

该通知的发送由重复的AlarmManager 触发。通知本身内置在我的BroadcastReceiveronReceive 中(如here 所述)。因此,当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 beyond the ViewModel [...],据说

如果您的应用程序的一部分不影响 UI,您可能不需要 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 约定?
我应该使用其他架构吗?现在这对我来说似乎很有意义,因为 这是我只检索一次并且不必观察变化的东西。

【问题讨论】:

    标签: android mvvm broadcastreceiver viewmodel android-viewmodel


    【解决方案1】:

    ViewModel 在这种情况下的真正目的是什么?
    它会将您的数据转换为便于查看的格式吗?
    它会处理数据更新吗? (我的意思是,会不会有数据更新?似乎你有一段时间有一个通知)
    或者它只会把干净、同步的代码弄得杂乱无章,让它异步而没有真正的目的?

    如果您仅对最后一个问题回答“是”,则您可能不需要 ViewModel :) 你需要其他架构吗?不,你不需要架构。你需要显示一个通知,所以就去做吧!


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

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

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

    【讨论】:

    • 是的,这基本上就是我所做的,只是自己使用了一个 AsynTask 从存储库中获取数据,没有 ViewModel 和 LiveData 的东西,因为在这种情况下它确实没有增加任何价值
    【解决方案2】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-16
      • 1970-01-01
      • 1970-01-01
      • 2016-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多