iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 28
0

RxJava和LiveData都能用於資料查詢,前者有多種Operator支援,後者功能單純但有lifecycle-aware特性幫我們處理View的相關問題。兩者各有優點,搭配使用的話Google在一場演講中提到大致的概念:將兩者的職責分開,RxJava負責Repository取得資料的部分,LiveData則負責UI相關的部分。
https://ithelp.ithome.com.tw/upload/images/20180116/201038497VifMUESe9.png
          Architecture Components (GDD Europe '17)

這樣在撈資料時能用Operator協助處理,而View在使用資料時也能保有lifecycle-aware性質。

實作方式有Architecture Components提供LiveDataReactiveStreams,讓我們能將Flowable和LiveData相互轉換,或者也可以用MutableLiveData並在RxJava Observable的callback中更新value。

LiveDataReactiveStreams

透過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.
    }
});

幾個使用上需注意的地方:

  • Flowable只要資料有更新就會發送,但LiveData在inactive狀態下,即沒有Observer的時候是不會接收更新的,會保持著最後active狀態時的value,因此下次交給Observer的就不一定是Flowable最新的value。
  • Flowable發出error的時候LiveData的onChanged無法處理,會導致App crash,解決方式應是建立像Resource之類的wrapper,將資料和狀態打包起來,在onChanged中進行判斷,可參考Day8

RxJava + MutableLiveData

不使用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實在太常見了,還是建議花點時間練習,將來會很有幫助。


上一篇
RxJava2 and Room
下一篇
Firebase Crashlytics
系列文
Android Architecture30

尚未有邦友留言

立即登入留言