莫道桑榆晚,为霞尚满天。这篇文章主要讲述Android官方架构组件介绍之LiveData相关的知识,希望能为你提供帮助。
LiveDataLiveData
是一个用于持有数据并支持数据可被监听(观察)。和传统的观察者模式中的被观察者不一样,LiveData是一个生命周期感知
组件,因此观察者可以指定某一个LifeCycle
给LiveData,并对数据进行监听。
如果观察者指定LifeCycle
处于Started
或者RESUMED
状态,LiveData会将观察者视为活动状态,并通知其数据的变化。
我们看一段代码:
public class LocationLiveData extends LiveData< Location> { private LocationManager locationManager; private SimpleLocationListener listener = new SimpleLocationListener() { @Override public void onLocationChanged(Location location) { setValue(location); } }; public LocationLiveData(Context context) { locationManager = (LocationManager) context.getSystemService( Context.LOCATION_SERVICE); }@Override protected void onActive() { locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener); }@Override protected void onInactive() { locationManager.removeUpdates(listener); } }
上面有三个值得注意的地方:
- onActive()
- onInactive()
- setValue()
接着我们就能像下面这样使用LocationLiveData了。
public class MyFragment extends LifecycleFragment { public void onActivityCreated (Bundle savedInstanceState) { LiveData< Location> myLocationListener = ...; Util.checkUserStatus(result -> { if (result) { myLocationListener.addObserver(this, location -> { // update UI }); } }); } }
注意上面的
addObserver
方法,我们将LifeCycleOwner
作为第一个参数传递了进去,这表示我们的LocationLiveData将遵照这个Fragment所持有的LifeCycle办事。- 如果LifeCycle不在Started或者RESUMED这两个状态,那么观察者将无法接受到数据更新的回调,即使数据发生了变化。
- 如果LifeCycle销毁了,即生命周期结束,观察者将被自动从LiveData中移除。
public class LocationLiveData extends LiveData< Location> { private static LocationLiveData sInstance; private LocationManager locationManager; @MainThread public static LocationLiveData get(Context context) { if (sInstance == null) { sInstance = new LocationLiveData(context.getApplicationContext()); } return sInstance; }private SimpleLocationListener listener = new SimpleLocationListener() { @Override public void onLocationChanged(Location location) { setValue(location); } }; private LocationLiveData(Context context) { locationManager = (LocationManager) context.getSystemService( Context.LOCATION_SERVICE); }@Override protected void onActive() { locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener); }@Override protected void onInactive() { locationManager.removeUpdates(listener); } }
这里使用单例的原因就是让多个Activity或者Fragment共享一个LocationLiveData实例。
然后我们可以这么使用:
public class MyFragment extends LifecycleFragment { public void onActivityCreated (Bundle savedInstanceState) { Util.checkUserStatus(result -> { if (result) { MyLocationListener.get(getActivity()).addObserver(this, location -> { // update UI }); } }); } }
通过这么一改,现在即使有多个Activity或者Fragment在使用LocationLiveData,它也能对其进行优雅的管理。不必理会页面销毁带来的诸多麻烦。
总结几点LiveData的有点:
- 没有内存溢出
- 不会因为Activity的不可见导致Crash
- 配置的改变
- 资源共享
- 不再有人为生命周期处理
LiveData的转换有时候有这样的需求,需要在LiveData将变化的数据通知给观察者前,改变数据的类型;或者是返回一个不一样的LiveData。
这里介绍一个类
Transformations
,它可以帮助完成上面的这些操作。- Transformations.map()
LiveData< User> userLiveData = https://www.songbingjia.com/android/...; LiveData< String> userName = Transformations.map(userLiveData, user -> { user.name +" " + user.lastName });
这里我们如果只需要知道变化用户的名字,那么只要观察userName这个LiveData对象即可。它会从userLiveData数据中提取用户名并传递给它自己的观察者。
- Transformations.switchMap()
private LiveData< User> getUser(String id) { ...; }LiveData< String> userId = ...; LiveData< User> user = Transformations.switchMap(userId, id -> getUser(id) );
当你考虑在ViewModel中使用LifeCycle对象时,这种转换就是一个可选的解决方案。
假如有一下需求,用户输入一个地址,我们在屏幕上更新这个地址对应的邮编,简单的写法如下:
class MyViewModel extends ViewModel { private final PostalCodeRepository repository; public MyViewModel(PostalCodeRepository repository) { this.repository = repository; }private LiveData< String> getPostalCode(String address) { // DON\'T DO THIS return repository.getPostCode(address); } }
这样写问题显然很严重,当每次调用getPostalCode方法后,UI代码中都需要对getPostalCode的返回值做注册观察者操作,并且还要移除上一个观察者,这样显然是低效率的。此外,如果这时UI因为配置的变化(屏幕旋转)重建了,那么它会触发再次调用getPostalCode,而不是使用之前的调用结果。
因此我们可以做如下转换:
class MyViewModel extends ViewModel { private final PostalCodeRepository repository; private final MutableLiveData< String> addressInput = new MutableLiveData(); public final LiveData< String> postalCode = Transformations.switchMap(addressInput, (address) -> { return repository.getPostCode(address); }); public MyViewModel(PostalCodeRepository repository) { this.repository = repository }private void setInput(String address) { addressInput.setValue(address); } }
【Android官方架构组件介绍之LiveData】注意,这里我们将postalCode访问限制符写成public final,因为它将始终不变,UI只要在需要用的时候将观察者注册到postalCode中就行。这是当用户调用setInput后,如果postalCode上有可活动的观察者,那么repository.getPostCode(address)就会被调用,如果此时没有可活动的观察者,则repository.getPostCode(address)不会被调用。
自定义转换在你的应用中可能需要除了上面两种以外更多的LiveData的转换,为了实现这些转换,你可以使用
MediatorLiveData
类,它可以用来正确的处理其他多个LiveData的事件变化,并处理这些事件。MediatorLiveData会将自身的active/inactive
状态变化正确的传递给它所处理的LiveData,例如MediatorLiveData没有观察者的话本文转自https://www.cnblogs.com/zqlxtt/p/6887940.htm
推荐阅读
- Android官方架构组件介绍之LifeCycle
- Android 前台服务
- Tp5框架 关于App登录token唯一加密算法
- QQ空间怎样开通黄钻LV9?开通办法介绍
- TIM聊天窗口怎样取消置顶?_其它聊天
- 微信排版有啥技巧?微信公众号排版技巧分享_微信
- 2017微信怎样解除手机绑定?微信解除手机绑定的办法_微信
- 微信有哪些好用的小程序?19款好用的微信小程序_微信
- 微信群验证消息怎样设置?_微信