思考从网络请求数据的异步任务,通常使用AsyncTask或其他方式将异步任务与当前活动绑定在一起。这样做有很多风险,活动的负担太重,线程也不能及时的关闭。或者把异步任务封装在工具类里,利用接口回调得到数据,但是这样也不是很好。下面看看rx怎么实现从网上下载一张图片并赋值给UI:
别忘了添加网络权限
1.首先创建一个工具类并写一个方法,返回值为一个观察者,泛型是想要的数据(字节数组):
public class DownLoadUtil {
private OkHttpClient client;
public DownLoadUtil(){
client=new OkHttpClient();
}
public Observable<byte []> download(String path){
return Observable.create(new Observable.OnSubscribe<byte[]>() {
@Override
public void call(Subscriber<? super byte[]> subscriber) {
if (!subscriber.isUnsubscribed()){
//在这里访问网络并发送数据
Request request=new Request.Builder().url(path).build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()){
subscriber.onNext(response.body().bytes());
subscriber.onCompleted();
}
}
});
}
}
});
}
}
使用OkHttp进行网络请求,拿到字节数组后调用观察者的onNext进行发送。
2.在活动中创建这个被观察者并订阅自定义的观察者,在onNext中处理数据:
DownLoadUtil util=new DownLoadUtil();
util.download(path).observeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<byte[]>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(byte[] bytes) {
Bitmap bitmap=BitmapFactory.decodeByteArray(bytes,0,bytes.length);
iv.setImageBitmap(bitmap);
}
});
被观察者调用的两个observeOn第一个是指任务在网络请求中执行涉及io,第二个表示任务在主线程执行。我的这段代码是写在一个点击事件中,虽然涉及UI操作,但是因为指定在主线程执行所以没有任何问题。
可以看到整个结构非常清晰,异步网络任务在被观察者中进行,拿到数据后发送给观察者,观察者进行UI赋值等操作。首先活动的负担大大减少,其次异步线程也很好控制。