(1)combineLatest基礎(chǔ)
RxJava的combineLatest()函數(shù)有點(diǎn)像zip()函數(shù)的特殊形式。
zip()
作用于最近未打包的兩個(gè)Observables揖闸,其中一個(gè)Observable發(fā)射數(shù)據(jù)項(xiàng)后揍堕,組合所有Observable最早一個(gè)未被組合的數(shù)據(jù)項(xiàng)相反;-
combineLatest()
作用于最近發(fā)射的數(shù)據(jù)項(xiàng)汤纸,在其中一個(gè)Observable發(fā)射數(shù)據(jù)項(xiàng)后鹤啡,組合所有Observable所發(fā)射的最后一個(gè)數(shù)據(jù)項(xiàng)(前提是所有的Observable都至少發(fā)射過(guò)一個(gè)數(shù)據(jù)項(xiàng)),如下圖所示;
其原理即:如果Observable1發(fā)射了1,接著Observable2發(fā)射了A,combineLatest()將會(huì)處理1和A蹲嚣,組合成1A递瑰;而Observable1發(fā)射了2,此時(shí)Observable2只發(fā)射了A隙畜,所以combineLatest()將處理2和A抖部,組合成2A;待Observable2發(fā)射了B時(shí)议惰,此時(shí)Observable1發(fā)射的最后一個(gè)數(shù)據(jù)是2慎颗,combineLatest()將處理2和B,組合成2B言询;以此類(lèi)推組合成2C俯萎,2D,3D等等运杭。
(2)combineLatest項(xiàng)目實(shí)戰(zhàn)
- EditText表單的校驗(yàn)
這個(gè)示例中夫啊,包含用戶(hù)名、密碼輸入框辆憔,它們的長(zhǎng)度要求分別為2~8 和 4~16撇眯,如果兩者都正確报嵌,那么登錄按鈕的文案變?yōu)椤暗卿洝保駝t顯示“用戶(hù)名或密碼無(wú)效”熊榛。
public class CombineLatestActivity extends AppCompatActivity {
private EditText mEtName;
private EditText mEtPassword;
private Button mBtLogin;
private PublishSubject<String> mNameSubject;
private PublishSubject<String> mPasswordSubject;
private CompositeDisposable mCompositeDisposable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_combine_latest);
mEtName = (EditText) findViewById(R.id.et_name);
mEtPassword = (EditText) findViewById(R.id.et_password);
mBtLogin = (Button) findViewById(R.id.bt_login);
//創(chuàng)建Subject
mNameSubject = PublishSubject.create();
mPasswordSubject = PublishSubject.create();
//添加EditText輸入監(jiān)聽(tīng)
mEtName.addTextChangedListener(new EditTextMonitor(mNameSubject));
mEtPassword.addTextChangedListener(new EditTextMonitor(mPasswordSubject));
//創(chuàng)建被觀(guān)察者
Observable<Boolean> observable = Observable.combineLatest(mNameSubject, mPasswordSubject, new BiFunction<String, String, Boolean>() {
@Override
public Boolean apply(String name, String password) throws Exception {
int nameLen = name.length();
int passwordLen = password.length();
return nameLen >= 2 && nameLen <= 8 && passwordLen >= 4 && passwordLen <= 16;
}
});
//創(chuàng)建觀(guān)察者
DisposableObserver<Boolean> disposable = new DisposableObserver<Boolean>() {
@Override
public void onNext(Boolean value) {
mBtLogin.setText(value ? "登錄" : "用戶(hù)名或密碼無(wú)效");
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
};
observable.subscribe(disposable);
mCompositeDisposable = new CompositeDisposable();
mCompositeDisposable.add(disposable);
}
private class EditTextMonitor implements TextWatcher {
private PublishSubject<String> mPublishSubject;
EditTextMonitor(PublishSubject<String> publishSubject) {
mPublishSubject = publishSubject;
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
//發(fā)射數(shù)據(jù)
mPublishSubject.onNext(s.toString());
}
}
@Override
protected void onDestroy() {
super.onDestroy();
mCompositeDisposable.clear();
}
}
- 需求-對(duì)A對(duì)象上的某個(gè)List屬性進(jìn)行RxJava操作, 然后把操作的結(jié)果再重新賦給原來(lái)的A對(duì)象
比如返回一個(gè)用戶(hù)信息User, 里面有List屬性表示他的好友, 但好友的信息只有id, 需要再次通過(guò)id獲取好友具體信息
//獲取用戶(hù)信息
userApi.fetchUserInfo()
.flatMap(new Func1<User, Observable<User>>() {
@Override
public Observable<User> call(User user) {
printLog(tvLogs, "----fetch a user---- \n", getUserString(user))
return fetchFriendsInfo(user);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<User>() {
@Override
public void call(User user) {
printLog(tvLogs, "----process his friends by id---- \n", getUserString(user));
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
throwable.printStackTrace();
}
});
獲取好友信息并組合
//這個(gè)方法才是實(shí)現(xiàn)的核心
private Observable<User> fetchFriendsInfo(User user) {
//保存User的數(shù)據(jù)
Observable<User> observableUser = Observable.just(user);
//對(duì)User的好友列表進(jìn)行單獨(dú)處理
Observable<List<User>> observableUsers = Observable.from(user.getFriends())
.flatMap(new Func1<User, Observable<User>>() {
@Override
public Observable<User> call(User user) {
//根據(jù)好友ID獲取更完整的信息
return userApi.fetchUserInfo(user.getId() + "");
}
})
.toList();
//對(duì)用戶(hù)User信息和他的好友信息進(jìn)行合并.
return Observable.combineLatest(observableUser, observableUsers, new Func2<User, List<User>, User>() {
@Override
public User call(User user, List<User> users) {
user.setFriends(users);
return user;
}
});
}
上面大致的意思就是把User信息分為兩個(gè)部分:一部分是用戶(hù)信(Observable<User>), 一部分是好友列表(Observable<List<User>>)信息 锚国,然后把兩個(gè)最終數(shù)據(jù)進(jìn)行組合