(1)combineLatest基础
RxJava的combineLatest()函数有点像zip()函数的特殊形式。
zip()
作用于最近未打包的两个Observables,其中一个Observable发射数据项后,组合所有Observable最早一个未被组合的数据项相反;-
combineLatest()
作用于最近发射的数据项,在其中一个Observable发射数据项后,组合所有Observable所发射的最后一个数据项(前提是所有的Observable都至少发射过一个数据项),如下图所示;
其原理即:如果Observable1发射了1,接着Observable2发射了A,combineLatest()将会处理1和A,组合成1A;而Observable1发射了2,此时Observable2只发射了A,所以combineLatest()将处理2和A,组合成2A;待Observable2发射了B时,此时Observable1发射的最后一个数据是2,combineLatest()将处理2和B,组合成2B;以此类推组合成2C,2D,3D等等。
(2)combineLatest项目实战
- EditText表单的校验
这个示例中,包含用户名、密码输入框,它们的长度要求分别为2~8 和 4~16,如果两者都正确,那么登录按钮的文案变为“登录”,否则显示“用户名或密码无效”。
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);
//创建Subject
mNameSubject = PublishSubject.create();
mPasswordSubject = PublishSubject.create();
//添加EditText输入监听
mEtName.addTextChangedListener(new EditTextMonitor(mNameSubject));
mEtPassword.addTextChangedListener(new EditTextMonitor(mPasswordSubject));
//创建被观察者
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;
}
});
//创建观察者
DisposableObserver<Boolean> disposable = new DisposableObserver<Boolean>() {
@Override
public void onNext(Boolean value) {
mBtLogin.setText(value ? "登录" : "用户名或密码无效");
}
@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) {
//发射数据
mPublishSubject.onNext(s.toString());
}
}
@Override
protected void onDestroy() {
super.onDestroy();
mCompositeDisposable.clear();
}
}
- 需求-对A对象上的某个List属性进行RxJava操作, 然后把操作的结果再重新赋给原来的A对象
比如返回一个用户信息User, 里面有List属性表示他的好友, 但好友的信息只有id, 需要再次通过id获取好友具体信息
//获取用户信息
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();
}
});
获取好友信息并组合
//这个方法才是实现的核心
private Observable<User> fetchFriendsInfo(User user) {
//保存User的数据
Observable<User> observableUser = Observable.just(user);
//对User的好友列表进行单独处理
Observable<List<User>> observableUsers = Observable.from(user.getFriends())
.flatMap(new Func1<User, Observable<User>>() {
@Override
public Observable<User> call(User user) {
//根据好友ID获取更完整的信息
return userApi.fetchUserInfo(user.getId() + "");
}
})
.toList();
//对用户User信息和他的好友信息进行合并.
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信息分为两个部分:一部分是用户信(Observable<User>), 一部分是好友列表(Observable<List<User>>)信息 ,然后把两个最终数据进行组合