1

LiveData 개체에 의해 반환 된 한 가지 유형의 데이터를 배경 지연의 다른 양식 으로 변환하여 UI 지연을 방지해야합니다. 내 특정 경우백그라운드 스레드에서 LiveData 변환을 수행하려면 어떻게합니까?

, 내가 가진 :

  • MyDBRow 객체 (POJO를 기본 long들로 구성된 String들);
  • RoomDAOLiveData<List<MyDBRow>>; 및
  • 풍부한 MyRichObject 객체 (예를 들어 date/time objects로 팽창 프리미티브와 POJO를)

을 기대하고 UI는 그래서하지 UI 스레드LiveData<List<MyDBRow>>LiveData<List<MyRichObject>>로하지만, 변환해야합니다.

Transformations.map(LiveData<X>, Function<X, Y>) 방법이 필요한 변환 않지만 메인 쓰레드의 변환을 실행하기 때문에이를 사용할 수

의해 출사 각 값에 메인 쓰레드에 소정 함수를 적용 source LiveData를 호출하고 결과 값을 내보내는 LiveData를 반환합니다.

주어진 함수 func은 주 스레드에서 실행됩니다.

LiveData 변환을 만들 수있는 깨끗한 방법은 무엇입니까가 발생합니다 메인 스레드 오프

  1. , 필요한 때만
  2. 가 (즉, 뭔가 의도 된 변화를 관찰하는 경우에만)?

답변

2
  • 원래는 "소스"는 LiveDataObserver 새로운 인스턴스에 의해 모니터링 될 수있다.
  • Observer 인스턴스의 경우 소스 LiveData이 방출되면 필요한 변환을 수행 한 후 "변형 된"새 LiveData을 통해 백그라운드 스레드를 준비 할 수 있습니다.
  • LiveData 소스 LiveData가 활성화 Observer S를 가진다 상기 Observer를 부착하고, 소스 LiveData가 필요할 때에 만 관찰되고 있다는 것을 보장하지 않는 경우들을 분리 할 수 ​​변환.

이 질문은 소스 코드 LiveData<List<MyDBRow>>을 제공하며 변형 된 LiveData<List<MyRichObject>>이 필요합니다.다수의 이러한 변환이 필요

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

과 주어진 예를 들어 서브 클래스 A는 다음과 같이 보일 수 LiveDataObserver 변형 합친 질문에 의해 다음과 같이 보일 수 있습니다.

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