Ale*_*ers 13 android android-thread android-room android-architecture-lifecycle android-architecture-components
我需要将一个LiveData对象返回的一种数据转换为后台线程上的另一种形式,以防止UI滞后.
在我的具体案例中,我有:
MyDBRow对象(由原始longs和Strings 组成的POJO );LiveData<List<MyDBRow>>; 和MyRichObject对象(POJO与原语膨胀成例如日期/时间对象)所以我需要将我LiveData<List<MyDBRow>>变成一个LiveData<List<MyRichObject>>,但不是在UI线程上.
该Transformations.map(LiveData<X>, Function<X, Y>)方法需要转换,但我不能使用它,因为它在主线程上执行转换:
将主线程上的给定函数应用于
sourceLiveData 发出的每个值,并返回生成结果值的LiveData.给定的函数
func将在主线程上执行.
什么是进行LiveData转换的简洁方法:
Ale*_*ers 17
LiveData可以由新Observer实例监视.Observer实例,当LiveData发出源时,可以准备一个后台线程来执行所需的转换,然后通过一个新的"转换"发出它LiveData.LiveData可以在上面有活动的时候将前面的内容附加Observer到源上,当它没有时,可以将它们分开,确保只在必要时观察到源.LiveDataObserverLiveData这个问题提供了一个示例源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);
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
如果需要多个这样的转换,上面的逻辑可以像这样通用:
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);
}
Run Code Online (Sandbox Code Playgroud)
并且问题给出的示例的子类看起来像这样:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
听 aMediatorLiveData<T>听另外两个LiveData<T>s。
例如:
val exposed: LiveData<List<T>> = MediatorLiveData<List<T>>().apply {
addSource(aLiveDataToMap) { doWorkOnAnotherThread(it) }
addSource(aMutableLiveData) { value = it }
}
private fun doWorkOnAnotherThread(t: T) {
runWorkOnAnotherThread {
val t2 = /* ... */
aMutableLiveData.postValue(t2)
}
}
Run Code Online (Sandbox Code Playgroud)
每当aLiveDataToMap发生变化时,它就会触发,doWorkOnAnotherThread()然后设置 的值aMutableLiveData,最终设置为 的值exposed,生命周期所有者将监听该值。将 s替换T为您想要的类型。
使用它可能是更好的方法MediatorLiveData.在引擎盖下Transformations.map()实施MediatorLiveData.
@MainThread
public static <X, Y> LiveData<Y> mapAsync(
@NonNull LiveData<X> source,
@NonNull final Function<X, Y> mapFunction) {
final MediatorLiveData<Y> result = new MediatorLiveData<>();
result.addSource(source, new Observer<X>() {
@Override
public void onChanged(@Nullable final X x) {
AsyncTask.execute(new Runnable() {
@Override
public void run() {
result.postValue(mapFunction.apply(x));
}
});
}
});
return result;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4455 次 |
| 最近记录: |