Android MediatorLiveData
- 可以监听多个 LiveData 源,并且能动态添加和移除源
合并多个 LiveData 源
1public class CombineViewModel extends ViewModel { 2 private final MutableLiveData<One> _oneLiveData = new MutableLiveData<>(); 3 public final LiveData<One> oneLiveData = _oneLiveData; 4 5 private final MutableLiveData<Two> _twoLiveData = new MutableLiveData<>(); 6 public final LiveData<Two> twoLiveData = _twoLiveData; 7 8 //MediatorLiveData 9 private final MediatorLiveData<CombinedData> _combinedData = new MediatorLiveData<>(); 10 public final LiveData<CombinedData> combinedData = _combinedData; 11 12 private boolean isOneReceived = false; 13 private boolean isTwoReceived = false; 14 15 //构造函数 16 public CombineViewModel() { 17 // 监听 One 数据源 18 _combinedData.addSource(_oneLiveData, one -> { 19 isOneReceived = true; 20 mergeData(); 21 }); 22 23 // 监听 Two 数据源 24 _combinedData.addSource(_twoLiveData, two -> { 25 isTwoReceived = true; 26 mergeData(); 27 }); 28 } 29 30 private void mergeData() { 31 // 仅当两个数据源都收到新更新时,才执行合并 32 if (isOneReceived && isTwoReceived) { 33 // 获取当前两个数据源的最新值(允许 null) 34 One currentOne = _oneLiveData.getValue(); 35 Two currentTwo = _twoLiveData.getValue(); 36 // 合并数据(即使有 null 也合并) 37 _combinedData.setValue(new CombinedData(currentOne, currentTwo)); 38 // 重置标志位:保证每轮双源更新仅合并一次 39 isOneReceived = false; 40 isTwoReceived = false; 41 } 42 } 43 44 @Override 45 protected void onCleared() { 46 super.onCleared(); 47 _combinedData.removeSource(_oneLiveData); 48 _combinedData.removeSource(_twoLiveData); 49 // 50 //isOneReceived = false; 51 //isTwoReceived = false; 52 } 53} 54
如果数据分布在不同 ViewModel 中
1public class CombineViewModel extends ViewModel { 2 //MediatorLiveData 3 private final MediatorLiveData<CombinedData> _combinedData = new MediatorLiveData<>(); 4 public final LiveData<CombinedData> combinedData = _combinedData; 5 // 6 private OneViewModel oneViewModel; 7 private TwoViewModel twoViewModel; 8 private boolean isOneReceived = false; 9 private boolean isTwoReceived = false; 10 11 public void init(ViewModelProvider viewModelProvider) { 12 clearSources(); 13 14 oneViewModel = viewModelProvider.get(OneViewModel.class); 15 twoViewModel = viewModelProvider.get(TwoViewModel.class); 16 17 //监听 One 数据源 18 _combinedData.addSource(oneViewModel.oneLiveData, one -> { 19 isOneReceived = true; 20 mergeData(); 21 }); 22 23 // 监听 Two 数据源 24 _combinedData.addSource(twoViewModel.twoLiveData, two -> { 25 isTwoReceived = true; 26 mergeData(); 27 }); 28 } 29 30 private void mergeData() { 31 if (isOneReceived && isTwoReceived) { 32 //双源都更新过才合并 33 One currentOne = oneViewModel.oneLiveData.getValue(); 34 Two currentTwo = twoViewModel.twoLiveData.getValue(); 35 // 更新合并后的数据(允许null) 36 _combinedData.setValue(new CombinedData(currentOne, currentTwo)); 37 // 重置标志位 38 isOneReceived = false; 39 isTwoReceived = false; 40 } 41 } 42 43 //清理监听 44 public void clearSources() { 45 if (oneViewModel != null) { 46 _combinedData.removeSource(oneViewModel.oneLiveData); 47 } 48 if (twoViewModel != null) { 49 _combinedData.removeSource(twoViewModel.twoLiveData); 50 } 51 oneViewModel = null; 52 twoViewModel = null; 53 // 54 isOneReceived = false; 55 isTwoReceived = false; 56 } 57 58 @Override 59 protected void onCleared() { 60 super.onCleared(); 61 // 62 clearSources(); 63 } 64} 65
Transformations#map
- 基于 MediatorLiveData
1private val _userLD = MutableLiveData<User>() 2val userLD: LiveData<User> = _userLD 3//更新用户信息 4fun updateUser(firstName: String, lastName: String, age: Int = 0) { 5 _userLD.value = User(firstName, lastName, age) 6} 7// User 转成 String 8val userFullNameLD: LiveData<String> = _userLD.map { user -> user.firstName + user.lastName } 9// Int 转成 String 10val ageTextLD: LiveData<String> = _userLD.map { user -> user.age.toString() } 11
感受一下源码
1//相当于 MediatorLiveData 收集(合并) 1 个 LiveData 源 2//从 LiveData<X> 转成 LiveData<Y>,比如 LiveData<User> 转成 LiveData<String> 3public fun <X, Y> LiveData<X>.map(mapFunction: Function<X, Y>): LiveData<Y> { 4 val combinedData = MediatorLiveData<Y>() 5 //监听 this 这个 LiveData 数据源 6 //转换好需要的值后再调用 combinedData#setValue 7 combinedData.addSource(this) { x -> combinedData.value = mapFunction.apply(x) } 8 return combinedData 9} 10
Transformations#switchMap
- 基于 MediatorLiveData
1private val _userIdLD: MutableLiveData<String> = MutableLiveData() 2val userIdLD: LiveData<String> = _userIdLD 3fun updateUserId(userId: String) { 4 _userIdLD.value = userId 5} 6//String 转 LiveData<User> (数据源动态切换) 7val userLD: LiveData<User> = _userIdLD.switchMap { userId -> userRepository.getUserByUserId(userId) } 8// 9
感受一下源码
1public fun <X, Y> LiveData<X>.switchMap(switchMapFunction: Function<X, LiveData<Y>>): LiveData<Y> { 2 val combinedData = MediatorLiveData<Y>() 3 //监听 this 这个 LiveData 数据源 4 combinedData.addSource(this, object : Observer<X> { 5 //主要是为了记录旧数据源,用作对比和移除操作 6 var liveData: LiveData<Y>? = null 7 override fun onChanged(value: X) { 8 //根据最新的 X 转成 LiveData(Y) 9 //比如 switchMapFunction.apply("002") 返回用户 userId=002 的 LiveData<User> 信息 10 val newLiveData = switchMapFunction.apply(value) 11 if (liveData === newLiveData) { 12 //引用相等,说明 newLiveData 已经在被 combinedData 收集监听了,不需要继续 removeSource 再 addSource 重走一遍 13 return 14 } 15 if (liveData != null) { 16 //如果有旧的数据源,先移除监听,否则旧的数据还会被收集监听 17 combinedData.removeSource(liveData!!) 18 } 19 liveData = newLiveData 20 if (liveData != null) { 21 combinedData.addSource(liveData!!) { y -> combinedData.setValue(y) } 22 } 23 } 24 } 25 ) 26 return combinedData 27} 28
ViewModel 复用 UseCase 的方法
1private final MutableLiveData<String> _liveDataSetConfig = new MutableLiveData<>(); 2//<success,param> 回传 param 是为了方便监听的时候使用 3public final LiveData<Pair<Boolean, String>> liveDataSetConfig = Transformations.switchMap(_liveDataSetConfig, configUseCase::execute); 4public void setConfig(String param) { 5 _liveDataSetConfig.setValue(param); 6} 7
1//ConfigUseCase 2public LiveData<Pair<Boolean, String>> execute(String param) { 3 MutableLiveData<Pair<Boolean, String>> result = new MutableLiveData<>(); 4 ThreadUtil.runXxx(() -> { 5 try { 6 //耗时操作 7 boolean success = Api.setConfig(param); 8 XLog.i(TAG + " setConfig success= " + success); 9 result.postValue(Pair.create(success, param)); 10 } catch (Exception e) { 11 result.postValue(Pair.create(false, param)); 12 } 13 }); 14 return result; 15} 16
《Android MediatorLiveData》 是转载文章,点击查看原文。