没有看过Retrofit&&RXJava傻瓜式入门(上)的同学可以简单了解下。
官网给出的文档指出RXJava是一个通过观察序列来构成异步和基于事件的程序库,我们将它傻瓜地理解为一个帮助我们简化异步操作的库即可。通过RXJava提供的链式API,我们可以很清晰地处理多线程的异步操作。
在正式介绍RXJava前,我们可以先简单了解下观察者模式。
观察者(Observer)与被观察者(Observable)通过订阅Subscribe的形式联系起来,被观察者在准备OK的时候通过回调方法通知观察者,从而观察者能及时作出对应处理。
经典案例便是Button的点击操作,我们为Button设置的clickListener就可抽象理解为一个观察者,而Button本身就是被观察者,当我们点击按钮时就会把点击事件告知Listener,让我们得以处理点击事件。不明白回调机制的同学可以点这里。
了解了观察者模式那就可以继续往下看RXJava的简单用法和其逻辑的清晰性。
RXJava的傻瓜使用方式:
- 1 创建观察者
Subscriber<String> subscriber = new Subscriber<String>() {
@Override
public void onNext(String s) {
}
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onStart() {
}
};
}
这里的Subscriber是RXJava已经实现的一个观察者抽象类,其内部有我们常用的四个方法。
onNext():事件回调方法
onCompleted():事件完成标识
onError():事件异常标识
onStart():事件还会开始时执行此方法,可用来做一些loading操作
- 2创建被观察者
Observable observable = Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber< > subscriber) {
subscriber.onNext("");
subscriber.onCompleted();
}
});
需要注意的是onCompleted()与onError互相排斥,仅且只能存在一个。除了通过Observable.create的方式来创建被观察者,还可以通过.just(T)、.from(T[])来快速创建,这儿不再额外叙述。
- 3通过Scheduler调度线程
讲了这么多,终于到了控制线程的地方啦!我们可以通过Scheduler指定事件产生、回调、订阅、解订的线程,直接上代码:
observable
.subscribeOn(Schedulers.io()) // 指定 subscribe() 发生在 IO 线程
.observeOn(AndroidSchedulers.mainThread()) // 指定 Subscriber 的回调发生在主线程
这样我们就可已很清晰地在IO线程进行网络请求等耗时操作,在主线程更新UI。除了这两个线程外,还有很多其他线程可供选择,在这不再扩展。
- 4完成订阅 Subscribe
observable.subscribe(subscriber);
傻瓜式入门教学到这结束,此文的宗旨只是为了让初学者了解RXJava,不做深究其map,lift等变换。下面可以看一下具体的demo实现。
Retrofit&&RXJava结合 demo
- 1 将我们创建的Retrofit API接口返回值从Call改为Observable
public interface DoubanAPI {
@GET("v2/movie/us_box")
Observable<MovieInfo> getUSMovie();
}
- 2 实例化retrofit时添加以下Factory方法
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
- 3 通过接口函数获取被观察者,然后就能愉快地进行我们想要的操作了。
doubanService.getUSMovie().subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(subscriber);
- 4 最后将回调事件中获取到的数据传递给我们封装的adapter中,就万事具备了~
@Override
public void onCompleted() {
Toast.makeText(MainActivity.this, "getUSMovie Completed", Toast.LENGTH_SHORT).show();
}
@Override
public void onError(Throwable e) {
//mTextView.setText(e.getMessage());
Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
Log.e("lxg",e.getMessage());
}
@Override
public void onNext(MovieInfo movieInfo) {
if (movieInfo.getSubjects() != null) {
if (list != null) {
list.clear();
}
list.addAll(movieInfo.getSubjects());
adapter.notifyDataSetChanged();
}
}
if (list != null) {
adapter=new CommonRecyclerAdapter<MovieInfo.SubjectsBean>(this,R.layout.movie_item,list) {
@Override
protected void convert(ViewHolder holder, MovieInfo.SubjectsBean subjectBean) {
holder.setText(R.id.titleTextView,subjectBean.getSubject().getTitle());
holder.setImageURI(R.id.contentImageView,subjectBean.getSubject().getImages().getLarge());
}
};
mrecycler.setAdapter(adapter);
}
解析后的Json数据只需取我们要用的list即可,这样一个异步获取网络数据并更新ui的简单界面就完成了。