LiveData

1.LifecycleOwner

Activityt等组件都是以LifecycleOwner的形式被LiveData感知的,LifecycleOwner只是一个简单的接口:

public interface LifecycleOwner {
    Lifecycle getLifecycle();
}

但是普通的Activity和Fragment并没有实现这个接口,想要使用LiveData的特性需要使用:

import android.support.v7.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
	...
}

import android.support.v4.app.Fragment;
public class MainFragment extends Fragment {
 	...
}
2.LiveData

LiveData是一个没有抽象方法的抽象类,它发射数据的方法的接口没有暴露给外部使用

public abstract class LiveData<T> {

	protected void postValue(T value) {...}

	@MainThread
    protected void setValue(T value) {...}

	@MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {...}

	@MainThread
    public void observeForever(@NonNull Observer<T> observer) {...}
}

MutableLiveData继承了LiveData,它只是暴露了发射数据的接口

public class MutableLiveData<T> extends LiveData<T> {
    @Override
    public void postValue(T value) {
        super.postValue(value);
    }

    @Override
    public void setValue(T value) {
        super.setValue(value);
    }
}

MediatorLiveData继承了MutableLiveData,它提供了addSource的接口

public class MediatorLiveData<T> extends MutableLiveData<T> {
	private SafeIterableMap<LiveData<?>, Source<?>> mSources = new SafeIterableMap<>();
	
 	@MainThread
    public <S> void addSource(@NonNull LiveData<S> source, @NonNull Observer<S> onChanged){...}

	@MainThread
    public <S> void removeSource(@NonNull LiveData<S> toRemote)

	private static class Source<V> implements Observer<V> {
		final LiveData<V> mLiveData;
        final Observer<V> mObserver;
	}
}

MediatorLiveData的作用是,考虑到有些页面可能有非常多的LiveData,每个Livedata都要绑定到一个生命周期对象,这样就产生了大量的重复代码;

	livedata1, livedata2..... livedata20;
	livedata1.observe(owner, result->{})
	livedata2.observe(owner, result->{})
	...
	livedata20.observe(owner, result->{})

MediatorLiveData类似于一个Map,它把liveData和它的观察者储存在这个Map中管理起来,MediatorLiveData自己去绑定并管理生命周期,这样就避免了每个LiveData都去绑定生命周期

	mediatorLiveData.addSource(livedata1, observer1);
	mediatorLiveData.addSource(livedata2, observer2);
	...
	mediatorLiveData.observe(lifecycleOwner, mediatOrbserver);
3.Transformations

Transformations提供了两个静态方法,它是用来对LiveData做变换的:

public class Transformations {
    @MainThread
    public static <X, Y> LiveData<Y> map(@NonNull LiveData<X> source, @NonNull final Function<X, Y> func) {
        final MediatorLiveData<Y> result = new MediatorLiveData<>();
        result.addSource(source, new Observer<X>() {
            @Override
            public void onChanged(@Nullable X x) {
                result.setValue(func.apply(x));
            }
        });
        return result;
    }
    
    @MainThread
    public static <X, Y> LiveData<Y> switchMap(@NonNull LiveData<X> trigger,
            @NonNull final Function<X, LiveData<Y>> func) {
        final MediatorLiveData<Y> result = new MediatorLiveData<>();
        result.addSource(trigger, new Observer<X>() {
            LiveData<Y> mSource;

            @Override
            public void onChanged(@Nullable X x) {
                LiveData<Y> newLiveData = func.apply(x);
                if (mSource == newLiveData) {
                    return;
                }
                if (mSource != null) {
                    result.removeSource(mSource);
                }
                mSource = newLiveData;
                if (mSource != null) {
                    result.addSource(mSource, new Observer<Y>() {
                        @Override
                        public void onChanged(@Nullable Y y) {
                            result.setValue(y);
                        }
                    });
                }
            }
        });
        return result;
    }
}
map

map需要传入两个参数,一个是待变换的LiveData,另一个是变换函数,它可以理解为Rxjava中的map操作符

public interface Function<I, O> {
    O apply(I input);
}

使用非常简单,例如:

	MutableLiveData<String> originalLivedata = new MutableLiveData<>();
	LiveData<String> transformedLiveData = Transformations.map(originalLivedata , s -> s + "?");		

	originalLivedata.observe(this,result -> {		//Observer1
         Log.d("originalLivedata", result);
    });
    
	TransformedLiveData.observe(this,result -> {	//Observer2
         Log.d("TransformedLiveData", result);
    });
	
	originalLivedata.setValue("Test");

在上面的测试中,两个Observer都会收到消息,分别打印了 Test 和 Test?
所以transformedLiveData会监听originalLivedata

switchMap

switchMap传入的两个参数分别是一个LiveData和一个Function,这个Fuction把普通数据类型转化为LiveData数据类型
它和Rxjava中的flatMap操作符非常相似,是map的加强版:

	MutableLiveData<String> originalLiveData = new MutableLiveData<>();

    LiveData<String> transformedLiveData = Transformations.switchMap(originalLiveData, s -> {
         MutableLiveData liveData = new MutableLiveData();
         liveData.setValue(s + "?");
         return liveData;
    });

    originalLiveData.observe(this, result -> {
        Log.d("originalLivedata", result+"");
    });

    transformedLiveData.observe(this, result -> {
        Log.d("transformedLiveData", result);
    });
    
    originalLiveData.setValue("Test");

效果和上面map是一样的

5.LiveData数据缓存:

Test:

public class MainViewModel {
	public static MutableLiveData<String> liveData = new MutableLiveData<>();
}
public class MainActivity extends AppCompatActivity {
	@Override
    protected void onCreate(Bundle savedInstanceState) {
    	...
    	//先让livedata发送一条消息
		viewModel.liveData.postValue("Hello");
		//在liveData发送消息一段时间后打开第二个TestActivity
		Observable.timer(10, TimeUnit.SECONDS).subscribe(n-> startActivity(Intent(this, TestActivity.class))
        );
	}
}
public class TestActivity extends AppCompatActivity {
	@Override
    protected void onCreate(Bundle savedInstanceState) {
    	//打开TestActivity会收到livedata发送的最后一条消息,尽管发消息的时间是10s前
    	viewModel.liveData.observe(this, s ->  Log.e("TestActivity ", s));
	}
}

即一个生命周期对象监听一个Livedata的时候,会马上收到这个Livedata发送过的最后一条消息

Livedata的这种特性会导致这样一种情况:一个页面在退出前收到了一条来自某Livedata的消息M,当这个页面再次启动并重新订阅这个Livedata的时刻,会再次收到同一条消息M

为了消除Livedata的这个特性,可以将发送的消息加一层封装,用来拦截掉已经处理过的消息:

public class Event<T> {
    private T mContent;
    private boolean hasBeenHandled = false;

    public Event(T content) {
        if (content == null) {
            throw new IllegalArgumentException("null values in Event are not allowed.");
        }
        mContent = content;
    }

    public T getContentIfNotHandled() {
        if (hasBeenHandled) {
            return null;
        } else {
            hasBeenHandled = true;
            return mContent;
        }
    }

    public boolean hasBeenHandled() {
        return hasBeenHandled;
    }

    public T peekContent() {
        return mContent;
    }
}

发送消息的时候把消息封在Event中:

	livedata.postValue(new Event("Hello"));
	livedata.observe(this, event -> {
          String msg = event.getContentIfNotHandled();
          Log.d("LivedataCacheTest", result);
    });

这样就可以保证每条消息只会被处理一次

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值