什么是响应式编程
官方解释为:在计算机领域,响应式编程是一个专注于数据流和变化传递的异步编程范式。
是不是觉得不太懂,其实我也不太懂,但是翻了很多博客后我理解为:一项任务的起点跟终点是连续的,中间没有断过但是中间可以做拦截或者加工。
举个例子:
我渴了(起点),然后要去喝水(终点)。
起点(分发事件(Path):渴了)——>去餐厅——>打开冰箱——>拿出饮料——>终点(一饮而尽 消费事件)
分析:我们去餐厅是因为渴了,所以才去,因此去餐厅是在渴了的基础上发生的,到了餐厅打开冰箱,因为到了餐厅所以才能打开冰箱,因此打开冰箱要在到达餐厅的基础上来进行,打开冰箱后要拿出饮料,拿出饮料要在打开冰箱的基础上进行,然后一饮而尽,该事件就被消费了,也就是此次任务执行完毕。这中间没有断过,而且每一个操作是在上一个操作结束的基础上来进行的。这就是Rx思维
Rx思维举例
//TODO 第二步:需求:将String类型转换为Bitmap类型
Observable.just("https://img-blog.csdnimg.cn/20190626094453625.jpg")
//TODO 第三步:将String转换成Bitmap类型并传给下一层
.map(new Function<String, Bitmap>() {
@Override
public Bitmap apply(String s) throws Exception {
try {
URL url = new URL(s);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setConnectTimeout(3000);
int responseCode = urlConnection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
InputStream inputStream = urlConnection.getInputStream();
return BitmapFactory.decodeStream(inputStream);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
})
.observeOn(AndroidSchedulers.mainThread())//主线程
.subscribeOn(Schedulers.io())//子线程
//TODO 导火索,上面的算是检查逻辑,直到这里才开始执行
.subscribe(new Observer<Bitmap>() {
@Override//TODO 第一步(点击完下载按钮,先执行此方法也就是先弹出加载框)
public void onSubscribe(Disposable d) {
progressDialog = new ProgressDialog(MainActivity.this);
progressDialog.setTitle("正在加载中");
//显示加载框
progressDialog.show();
}
@Override//TODO 第四步:成功
public void onNext(Bitmap s) {
imageView.setImageBitmap(s);
}
@Override//TODO 链条思维发生了异常
public void onError(Throwable e) {
}
@Override//TODO 第五步:整个链条思维全部结束
public void onComplete() {
//隐藏加载框
if (progressDialog != null) {
progressDialog.dismiss();
}
}
});
我们需要从网上下载一张图片(起点),然后展示在图片控件上(终点)
//起点
Observable.just("https://img-blog.csdnimg.cn/20190626094453625.jpg")
//终点
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String s) {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
我们起点的的Path是String类型,所以终点的泛型也是Sting类型,因为终点是在起点的执行结果的基础上来进行的,但是我们的结构需要的是Bitmap类型,所以我们就需要来进行类型转换
//起点
Observable.just("https://img-blog.csdnimg.cn/20190626094453625.jpg")
//类型转换Sting——>Bitmap
.map(new Function<String, Bitmap>() {
@Override
public Bitmap apply(String s) throws Exception {
//进行网络请求
try {
URL url = new URL(s);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setConnectTimeout(3000);
int responseCode = urlConnection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
InputStream inputStream = urlConnection.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
inputStream.close();
return bitmap;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
})
//终点
.subscribe(new Observer<Bitmap>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Bitmap s) {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
又因为,我们的网络请求是在子线程中进行的,而UI更新是在主线程中进行,所以我们就需要进行线程的切换
//起点
Observable.just("https://img-blog.csdnimg.cn/20190626094453625.jpg")
//TODO 类型转换Sting——>Bitmap
.map(new Function<String, Bitmap>() {
@Override
public Bitmap apply(String s) throws Exception {
//进行网络请求
try {
URL url = new URL(s);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setConnectTimeout(3000);
int responseCode = urlConnection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
InputStream inputStream = urlConnection.getInputStream();
return BitmapFactory.decodeStream(inputStream);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
})
//TODO 线程切换
.observeOn(AndroidSchedulers.mainThread())//主线程
.subscribeOn(Schedulers.io())//子线程
//终点
.subscribe(new Observer<Bitmap>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Bitmap s) {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
然后就是拿到响应值来进行设置到图片控件上,这个时候你会发现没有加载的弹框出现,要想实现这个效果,我们需要先定义一个ProgressDialog,然后在终点的onSubscribe()方法中进行初始化与显示,且记要在链条思维结束后把弹框隐藏掉。
.subscribe(new Observer<Bitmap>() {
@Override//TODO 第一步(点击完下载按钮,先执行此方法也就是先弹出加载框)
public void onSubscribe(Disposable d) {
progressDialog = new ProgressDialog(MainActivity.this);
progressDialog.setTitle("正在加载中");
//显示加载框
progressDialog.show();
}
@Override//TODO 第四步:成功
public void onNext(Bitmap s) {
//设置图片
imageView.setImageBitmap(s);
}
@Override//TODO 链条思维发生了异常
public void onError(Throwable e) {
}
@Override//TODO 第五步:整个链条思维全部结束
public void onComplete() {
if (progressDialog != null) {
progressDialog.dismiss();
}
}
以上便是笔者理解的Rx思维,分享给大家希望能对大家有所帮助。