在后台线程或非UI组件中的LiveData

6
亲爱的。我曾经使用MVP模式开发Android应用程序,现在我正在尝试使用Architecture组件中的DataBind和LiveData进行MVVM。
我编写了一个提供LiveData的Repository类:
LiveData<MyEntity> getById(long id);

对于活动/片段,我观察由ViewModel(使用我的Repository)公开的LiveData,一切都很顺利。

问题是我必须安排一个闹钟来显示与MyEntity相关的文本通知,因此我创建了一个包含MyEntityId作为额外项的Intent。

当AlarmManager调用我的BroadcastReceiver时,我需要使用Repository获取MyEntity。关键是如何在非UI组件中“观察”LiveData。

另外,我可以启动IntentService(后台线程)以避免在主线程中访问Repository,并使用类似于RxJava的“blockingNext”,但我仍然无法想出等待LiveData的方法。

这样做的正确方式是什么?请注意,由于遗留问题,我的Repository可能没有使用Room实现。

谢谢

到目前为止,我找到的唯一解决方案是在Repository中拥有这样的方法:

LiveData<MyEntity> getByIdLive(long id);
MyEntity getById(long id);

但这对我来说不是一个好的展示。 因此,我想问如何正确实现这个。

最好的问候


我倾向于使用后缀“WithChanges”,例如getByIdWithChanges(long id) - EpicPandaForce
2个回答

1

最好避免这样的事情,但如果您真的需要并且确实知道自己在做什么,可以尝试以下代码:

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];
}

0

在我的项目中,添加像EventBus这样的库是不可能的。我会考虑实现一个包装器来等待LiveData,但由于没有优雅的方式,我可能会坚持使用我的Repository可以将结果作为LiveData和List<>两种形式提供的解决方案,以便在需要时使用。 - William Miranda

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接