如何在后台线程上执行LiveData转换? [英] How can I perform LiveData transformations on a background thread?

本文介绍了如何在后台线程上执行LiveData转换?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要将 LiveData 对象返回的一种类型的数据转换为在后台线程上的另一种形式,以防止UI滞后.

I have a need to transform one type of data, returned by a LiveData object, into another form on a background thread to prevent UI lag.

在我的特定情况下,我有:

In my specific case, I have:

  • MyDBRow 对象(由原始 long s和 String s组成的POJO);
  • a 房间
  • MyDBRow objects (POJOs consisting of primitive longs and Strings);
  • a Room DAO instance emitting these via a LiveData<List<MyDBRow>>; and
  • a UI expecting richer MyRichObject objects (POJOs with the primitives inflated into e.g. date/time objects)

所以我需要将我的 LiveData< List< MyDBRow> 转换为 LiveData< List< MyRichObject>> ,但是不在UI上线程.

so I need to transform my LiveData<List<MyDBRow>> into a LiveData<List<MyRichObject>>, but not on the UI thread.

将主线程上的给定函数应用于 source LiveData发出的每个值,并返回LiveData,后者发出结果值.

Applies the given function on the main thread to each value emitted by source LiveData and returns LiveData, which emits resulting values.

给定的函数 func 将在主线程上执行.

The given function func will be executed on the main thread.

进行 LiveData 转换的一种干净方法是什么

What is a clean way to make LiveData transformations occur:

  1. 离开主线程的某个地方,并且
  2. 仅在需要时(即仅在某些情况下正在观察预期的转换时)?

推荐答案

  • 原始的源" LiveData 可以由新的 Observer 实例.
  • 发出源 LiveData 时,此 Observer 实例可以准备后台线程以执行所需的转换,然后通过新的已转换"的 LiveData .
  • 转换后的 LiveData 可以在活动的 Observer 时将上述 Observer 附加到源 LiveData 上,并在不需要时分离它们,以确保仅在必要时才观察源 LiveData .
    • The original, "source" LiveData can be monitored by a new Observer instance.
    • This Observer instance, when source LiveData is emitted, can prepare a background thread to perform the needed transformation and then emit it via a new, "transformed" LiveData.
    • The transformed LiveData can attach the aforementioned Observer to the source LiveData when it has active Observers, and detach them when it doesn't, ensuring that the source LiveData is only being observed when necessary.
    • 该问题给出了示例源 LiveData< List< MyDBRow>> ,并且需要转换后的 LiveData< List< MyRichObject>> .组合后的转换后的 LiveData Observer 可能看起来像这样:

      The question gives an example source LiveData<List<MyDBRow>> and needs a transformed LiveData<List<MyRichObject>>. A combined transformed LiveData and Observer could look something like this:

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

      如果需要多次这样的转换,可以使上述逻辑通用,如下所示:

      If multiple such transformations are needed, the above logic could be made generic like this:

      abstract class TransformedLiveData<Source, Transformed>
              extends LiveData<Transformed>
              implements Observer<Source>
      {
          @Override protected void onActive()   { getSource().observeForever(this); }
          @Override protected void onInactive() { getSource().removeObserver(this); }
      
          @Override public void onChanged(@Nullable Source source) {
              AsyncTask.execute(new Runnable() {
                  @Override public void run() {
                      postValue(getTransformed(source));
                  }
              });
          }
      
          protected abstract LiveData<Source> getSource();
          protected abstract Transformed getTransformed(Source source);
      }
      

      以及该问题给出的示例的子类可能看起来像这样:

      and the subclass for the example given by the question could look something like this:

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

      这篇关于如何在后台线程上执行LiveData转换?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆