android – 如何在后台线程上执行LiveData转换?

前端之家收集整理的这篇文章主要介绍了android – 如何在后台线程上执行LiveData转换?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我需要将一个由LiveData对象返回的数据转换为后台线程上的另一种形式,以防止UI延迟.

在我的具体案例中,我有:

> MyDBRow对象(由原始long和字符串组成的POJO);
> a Room DAO实例通过LiveData< List< MyDBRow>>发出这些实例;和
>一个UI期待更丰富的MyRichObject对象(PO​​JO与原语膨胀到例如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 source LiveData and returns LiveData,which emits resulting values.

The given function func will 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;
    }
}
原文链接:https://www.f2er.com/android/318237.html

猜你在找的Android相关文章