RxJava和LiveData都能用於資料查詢,前者有多種Operator支援,後者功能單純但有lifecycle-aware特性幫我們處理View的相關問題。兩者各有優點,搭配使用的話Google在一場演講中提到大致的概念:將兩者的職責分開,RxJava負責Repository取得資料的部分,LiveData則負責UI相關的部分。
Architecture Components (GDD Europe '17)
這樣在撈資料時能用Operator協助處理,而View在使用資料時也能保有lifecycle-aware性質。
實作方式有Architecture Components提供LiveDataReactiveStreams,讓我們能將Flowable和LiveData相互轉換,或者也可以用MutableLiveData並在RxJava Observable的callback中更新value。
透過fromPublisher
我們可以在ViewModel中將Flowable<T>
轉換成LiveData<T>
,完成上圖的概念。
加入dependencies
// ReactiveStreams support for LiveData
implementation "android.arch.lifecycle:reactivestreams:1.0.0"
Repository中的Flowable:
public class UserRepository {
...
public Flowable<List<User>> getUsers() {
return userDao.getUsers();
}
}
ViewModel中使用fromPublisher
轉換成LiveData:
public class UserViewModel extends ViewModel {
private final LiveData<List<User>> users;
...
@Inject
public UserViewModel(UserRepository repository) {
Flowable<List<User>> flowable = repository.getUsers()
.observeOn(AndroidSchedulers.mainThread());
users = LiveDataReactiveStreams.fromPublisher(flowable);
}
LiveData<List<User>> getUsers() {
return users;
}
...
}
fromPublisher(flowable)
讓我們將Flowable<List<User>>
轉換成了LiveData<List<User>>
。
在View中的用法就跟一般LiveData一樣:
viewModel.getUsers().observe(this, new Observer<List<User>>() {
@Override
public void onChanged(@Nullable List<User> users) {
// Do something with users.
}
});
幾個使用上需注意的地方:
onChanged
無法處理,會導致App crash,解決方式應是建立像Resource之類的wrapper,將資料和狀態打包起來,在onChanged
中進行判斷,可參考Day8。不使用LiveDataReactiveStreams轉換的話,我們可以在ViewModel中subscribe並用setValue
更新MutableLiveData,這樣就不限於Flowable,可以使用任意的Observable。
public class UserRepository {
...
public Single<List<User>> getUsers() {
return service.getUsers();
}
}
public class UserViewModel extends ViewModel {
private final MutableLiveData<List<User>> users;
...
public void loadUsers() {
disposables.add(repository.getUsers()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableSingleObserver<List<User>>() {
@Override
public void onSuccess(List<User> data) {
users.setValue(data);
}
@Override
public void onError(Throwable e) {
// Error handle.
}
}));
}
LiveData<List<User>> getUsers() {
return users;
}
...
@Override
public void onCleard() {
super.onCleard();
disposables.clear();
}
}
記得在onCleard
時呼叫disposables.clear()
以防止memory leak。
LiveDataReactiveStreams是目前網路上資源最少的Architecture Components成員,尚未出現完整的App sample,我對它的理解也不像其他成員有在工作專案上實作過,只在發這篇文的時候做一點研究而已,如果上面有錯誤或能加強的地方還請不吝指教。
今天是RxJava的最後一篇,其實重要的都在Day25簡介和Day26 API連線,只要API處理得順手,後面的Room那些都相對簡單。想起當初入門RxJava時也是蠻痛苦,不過Android開發中切換thread實在太常見了,還是建議花點時間練習,將來會很有幫助。