之前我们通过如下两种方式创建过Obserable对象,
//just
Observable.just("hello");
//create方法
Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("android");
}
});
//from操作符,接收一个集合,打印出集合中每个内容
List<String> list = new ArrayList<>();
Observable.from(list).subscribe(new Action1<String>() {
@Override
public void call(String s) {
System.out.println("=======s"+s);
}
});
今天再来看一种方式
Observable<List<String>> observable = Observable.fromCallable(new Callable<List<String>>() {
@Override
public List<String> call() throws Exception {
//你的操作
return null;
}
});
那么fromCallable有什么特点呢?根据源码介绍,主要是下面这个特点
你所有进行操作的代码只会在该Obserable被订阅之后执行,不像just操作符,我们之前提到过,无论是都订阅,just中的操作都会执行,
注意:fromCallable中的操作并没有执行在某个固定的线程,也就是说我们如果需要进行网络等耗时操作时,还是要为该Obserable执行的线程。
你可能会见过如下两种方式订阅
//方式一
observable
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<List<String>>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(List<String> o) {
Toast.makeText(MainActivity.this, "执行", Toast.LENGTH_SHORT).show();
}
});
//方式二
mSubscription = observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<List<String>>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(List<String> strings) {
}
});
可以看到,这两种方式的唯一不同就是一个创建了 Observer对象,一个创建了Subscriber对象,连后面的方法都一样的,为什么呢?去看看源码就知道了。
public interface Observer<T> {
void onCompleted();
void onError(Throwable e);
void onNext(T t);
}
public abstract class Subscriber<T> implements Observer<T>, Subscription {
// represents requested not set yet
private static final Long NOT_SET = Long.MIN_VALUE;
private final SubscriptionList subscriptions;
private final Subscriber<?> subscriber;
/* protected by `this` */
private Producer producer;
/* protected by `this` */
private long requested = NOT_SET; // default to not set
protected Subscriber() {
this(null, false);
}
.....
}
这下明白了,Subscriber实现了Observer以及Subscription,功能更加丰富了,所以,在实际中见到了Subscriber会比较多,同时我们可以看到当我们调用订阅方法之后会返回一个Subscription对象,有什么用呢?用法如下
@Override
protected void onDestroy() {
super.onDestroy();
if(mSubscription!=null&&!mSubscription.isUnsubscribed()){
mSubscription.unsubscribe();
}
}
如果你与多线程打过交道,你肯定会意识到一个大坑:当Activity执行onDestroy()后线程才结束(甚至永不结束)的话,就有可能发生内存泄漏与NullPointerException空指针异常。
Subscription就可以解决这个问题,我们可以通过调用unsubscribe()方法告诉Observable它所发送的数据不再被Observer所接收。在调用unsubscribe()方法后,我们创建的Observer就不再会收到数据了,同时也就解决了刚才说的问题。
最后在讲一个操作符
我们要实现输入字符,在textview显示
mPublishSubject = PublishSubject.create();
mPublishSubject.debounce(2, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.map(new Func1<String, Integer>() {
@Override
public Integer call(String s) {
return Integer.parseInt(s);
}
}) .observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Integer>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
//发生异常后,订阅就结束了
}
@Override
public void onNext(Integer strings) {
//处理结果,显示给textview
mTextView.setText(strings+"");
}
});
et.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
Toast.makeText(MainActivity.this, "改变", Toast.LENGTH_SHORT).show();
mPublishSubject.onNext(s.toString());
}
@Override
public void afterTextChanged(Editable s) {
}
});
debounce的作用就是进行限制,这里我们没必要每次字符改变都去显示给TextView,这里我们限制只有在输入字符2000毫秒后没有字符没有改变时才去请求网络,节省了资源,在网络请求是这种限制显得更加重要。