在我的具体案例中,我有:
> MyDbrow对象(由原始long和字符串组成的POJO);
> a Room DAO实例通过LiveData< List< MyDbrow>>发出这些实例;和
>一个UI期待更丰富的MyRichObject对象(POJO与原语膨胀到例如date/time objects)
所以我需要转换我的LiveData< List< MyDbrow>>到一个LiveData< List< MyRichObject>>,但不在UI线程上.
Transformations.map(LiveData<X>,Function<X,Y>)方法执行此操作需要转换,但我不能使用它,因为它在主线程上执行转换:
Applies the given function on the main thread to each value emitted by
sourceLiveData and returns LiveData,which emits resulting values.The given function
funcwill be executed on the main thread.
什么是实现LiveData转换的简洁方法:
>离主线程的某个地方,和
>仅在需要时(即仅在某些事物正在观察预期的转变时)?
解决方法
LiveData可以由新的
Observer实例监控.
>此Observer实例在发出源LiveData时,可以准备后台线程来执行所需的转换,然后通过新的“转换”LiveData发出它.
>转换后的LiveData可以在具有活动观察者时将上述观察者附加到源LiveData,并在没有活动观察者时将其分离,确保仅在必要时观察源LiveData.
该问题给出了一个示例源LiveData< List< MyDbrow>>并需要转换后的LiveData< List< MyRichObject>>.组合转换的LiveData和Observer看起来像这样:
class MyRichObjectLiveData
extends LiveData<List<MyRichObject>>
implements Observer<List<MyDbrow>>
{
@NonNull private LiveData<List<MyDbrow>> sourceLiveData;
MyRichObjectLiveData(@NonNull LiveData<List<MyDbrow>> sourceLiveData) {
this.sourceLiveData = sourceLiveData;
}
// only watch the source LiveData when something is observing this
// transformed LiveData
@Override protected void onActive() { sourceLiveData.observeForever(this); }
@Override protected void onInactive() { sourceLiveData.removeObserver(this); }
// receive source LiveData emission
@Override public void onChanged(@Nullable List<MyDbrow> dbrows) {
// set up a background thread to complete the transformation
AsyncTask.execute(new Runnable() {
@Override public void run() {
assert dbrows != null;
List<MyRichObject> myRichObjects = new LinkedList<>();
for (MyDbrow myDbrow : myDbrows) {
myRichObjects.add(MyRichObjectBuilder.from(myDbrow).build());
}
// use LiveData method postValue (rather than setValue) on
// background threads
postValue(myRichObjects);
}
});
}
}
如果需要多个这样的转换,上面的逻辑可以像这样通用:
abstract class TransformedLiveData<Source,Transformed>
extends LiveData<Transformed>
{
private Observer<Source> observer = new Observer<Source>() {
@Override public void onChanged(@Nullable final Source source) {
AsyncTask.execute(new Runnable() {
@Override public void run() {
postValue(getTransformed(source));
}
});
}
};
@Override protected void onActive() { getSource().observeForever(observer); }
@Override protected void onInactive() { getSource().removeObserver(observer); }
protected abstract LiveData<Source> getSource();
protected abstract Transformed getTransformed(Source source);
}
并且问题给出的示例的子类可能如下所示:
class MyRichObjectLiveData
extends TransformedLiveData<List<MyDbrow>,List<MyRichObject>>
{
@NonNull private LiveData<List<MyDbrow>> sourceLiveData;
MyRichObjectLiveData(@NonNull LiveData<List<MyDbrow>> sourceLiveData) {
this.sourceLiveData = sourceLiveData;
}
@Override protected LiveData<List<MyDbrow>> getSource() {
return sourceLiveData;
}
@Override protected List<MyRichObject> getTransformed(List<MyDbrow> myDbrows) {
List<MyRichObject> myRichObjects = new LinkedList<>();
for (MyDbrow myDbrow : myDbrows) {
myRichObjects.add(MyRichObjectBuilder.from(myDbrow).build());
}
return myRichObjects;
}
}