亲爱的。我曾经使用MVP模式开发Android应用程序,现在尝试将MVVM与诸如DataBind和LiveData的体系结构组件一起使用。
我编写了提供LiveData的Repository类:
LiveData<MyEntity> getById(long id);
对于活动/片段,我观察到ViewModel(使用我的存储库)公开的LiveData,并且一切正常。
问题是我必须安排一个警报来显示带有与MyEntity相关的文本的通知,因此我创建了一个包含MyEntityId作为Extra的Intent。
当AlarmManager调用我的BroadcastReceiver时,我需要使用存储库来获取MyEntity。关键是如何在非UI组件中“观察” LiveData。
此外,我可以启动IntentService(后台线程)以避免访问主线程中的存储库,并使用RxJava中的“ blockingNext”之类的东西,但是我仍然找不到等待LiveData的方法。
这样做的正确方法是什么?请注意,由于遗留问题,我的存储库可能无法使用Room实施。
谢谢
到目前为止,我唯一想到的解决方案是在存储库中使用以下方法:
LiveData<MyEntity> getByIdLive(long id);
MyEntity getById(long id);
但这对我来说并不好。 所以我想问一下实现此方法的正确方法。
最好的问候
答案 0 :(得分:0)
您只能在UI组件(例如活动/片段)中观察liveData。
对于您的方案,您可以创建一个在非UI类中也可以观察到的观察者类,或者可以使用EventBus。
了解观察者:https://developer.android.com/reference/java/util/Observer
关于EventBus:https://github.com/greenrobot/EventBus
答案 1 :(得分:0)
最好避免这种情况,但是如果您确实需要它并且真的知道自己在做什么,则可以尝试以下代码:
public static <T> void observeOnce(final LiveData<T> liveData, final Observer<T> observer) {
liveData.observeForever(new Observer<T>() {
@Override
public void onChanged(T t) {
liveData.removeObserver(this);
observer.onChanged(t);
}
});
}
@WorkerThread
public static <T> T waitSync(final LiveData<T> liveData) {
final Object lock = new Object();
final Object[] result = new Object[1];
final boolean[] resultReady = new boolean[] {false};
(new Handler(Looper.getMainLooper())).post(new Runnable() {
@Override
public void run() {
observeOnce(liveData, new Observer<T>() {
@Override
public void onChanged(T t) {
synchronized (lock) {
result[0] = t;
resultReady[0] = true;
lock.notify();
}
}
});
}
});
synchronized (lock) {
try {
while (!resultReady[0]) {
lock.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
return null;
}
}
return (T) result[0];
}