在我的具体案例中,我有:@H_404_3@
> MyDBRow对象(由原始long和字符串组成的POJO);
> a Room DAO实例通过LiveData< List< MyDBRow>>发出这些实例;和
>一个UI期待更丰富的MyRichObject对象(POJO与原语膨胀到例如date/time objects)@H_404_3@
所以我需要转换我的LiveData< List< MyDBRow>>到一个LiveData< List< MyRichObject>>,但不在UI线程上.@H_404_3@
Transformations.map(LiveData<X>,Function<X,Y>)
方法执行此操作需要转换,但我不能使用它,因为它在主线程上执行转换:@H_404_3@
Applies the given function on the main thread to each value emitted by
source
LiveData and returns LiveData,which emits resulting values.@H_404_3@The given function
func
will be executed on the main thread.@H_404_3@
什么是实现LiveData转换的简洁方法:@H_404_3@
>离主线程的某个地方,和
>仅在需要时(即仅在某些事物正在观察预期的转变时)?@H_404_3@
解决方法
LiveData
可以由新的
Observer
实例监控.
>此Observer实例在发出源LiveData时,可以准备后台线程来执行所需的转换,然后通过新的“转换”LiveData发出它.
>转换后的LiveData可以在具有活动观察者时将上述观察者附加到源LiveData,并在没有活动观察者时将其分离,确保仅在必要时观察源LiveData.
该问题给出了一个示例源LiveData< List< MyDBRow>>并需要转换后的LiveData< List< MyRichObject>>.组合转换的LiveData和Observer看起来像这样:@H_404_3@
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); } }); } }
如果需要多个这样的转换,上面的逻辑可以像这样通用:@H_404_3@
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); }
并且问题给出的示例的子类可能如下所示:@H_404_3@
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; } }