retrofit是载体(基于okhttp),rxjava 就是一个实现异步操作的库。 它的简洁的与众不同之处在于,随着程序逻辑变得越来越复杂,它依然能够保持简洁。
就比如我们开了一家披萨店:
你总不能直接把披萨胚直接卖给客人
RX思维分析(完成披萨订单)
被观察者(起点)-------需求(1个或者多个)---------观察者(终点)
就是和卖批萨一样,一条流水线,你开始是个被观察者(披萨胚),观察者(客人)点餐提出需求,通过中间做这些需求(放芝士啥的)最后一个需求结束以后把参数(披萨成品)传给观察者(客人)
RX=反应式 reactive x==反应式==响应式编程思维RX == 响应式编程思维 什么是响应式编程? 答:根据上一层的响应来影响下一层的变化 (起点〉点击按钮触发方法---->请求服务器---->服务器的响应.---->解析响应的json数据界面展示出来(终点)
1.编写样式,并在按钮加一个自定义命名onclick事件
2.因为是加载网络图片,所以要manifest中开启网络权限
3.添加RXJava 3X依赖才能正常在mainActivity调用方法
4.编写MainActivity.java代码
效果图:
因为是异步,所以肯定不止一个需求,那么接下来我们再添加一个
就只需要在map后面加需求就好了
先去自定义了一个方法,然后再调用它
效果图:
Retrofit是一个网络请求框架的封装,底层网络请求默认使用OkHttp,也就是说Retrofit本身并不具备网络请求的能力,只是简化了网络请求的相关参数配置或者说Retrofit只负责上层接口的封装。
使用Retrofit,实际上是使用Retrofit接口层封装请求参数、Header、Url 等信息,之后由OkHttp完成后续的请求操作,当服务端返回数据之后,OkHttp再将原始的结果交给Retrofit,然后Retrofit根据用户的需求,对结果进行解析。
1.导入retrofit依赖
2.创建接口,这里只是定义rxjava的observable方法,@Url注解后面传入图片链接,ResponseBody是抽象类,它实例化的那部分它封装进去了在源码里后续我们只需要直接在mainActivity直接调用,通过string()字符流的方式读取内容,bytes()字节流的方式读取内容我们还可以获得字节流,实现自己的定制化读取。会在mainActivity写。
在原有的基础上改一下,首先在mainActivity创建接口对象,进行实例化
下面我们可以看见map里面okhttp在结合rxjava的时候不写接口,进行请求图片的时候需要写很多行代码,各种调用方法赋值。很繁琐。。。
3.Retrofit实例化
4.创建网络请求接口对象实例
5.编写map需求(关于下载下来的文件流格式转换这一块)这个需求完成(加工完成)以后会将bitmap图片传给观察者(客人)里面的onNext()方法。如果要是有别的需求,会把bitmap图片传到下一个需求,只有把需求全部完成才会传给onNext()方法。
在onnext我们也可以除了展示做其他操作,这里就只写了一个展示功能,onnext执行完成以后如果成功跑完,就会执行complete方法,弹窗隐藏,如果期间我们点击了别的地方啥的导致无法正常跑完就会执行onError报错。
周期梳理:
效果图:
学习期间疑惑点解答:
1.Retrofit2的使用(接口数据请求关于注解用法)
Retrofit2 详解和使用(一)_锐湃的博客-CSDN博客_retrofit2使用详解^v63^js_top,201^v3^control_1,213^v2^t3_esquery_v1&utm_term=Streaming%E6%B3%A8%E8%A7%A3&spm=1018.2226.3001.4187
2.Retrofit2+RXJava3框架搭建
java 图片下载案例_Retrofit Rxjava实现图片下载、保存并展示实例_杨勃 (阿北)的博客-CSDN博客^v63^js_top,201^v3^control_1,213^v2^t3_esquery_v1&utm_term=retrofit2%E5%9B%BE%E7%89%87%E4%B8%8B%E8%BD%BD&spm=1018.2226.3001.4187
3.RXJava思想教学视频--OKHTTP3+RXJava3框架搭建(建议加依赖使用RXJava3)
1.RX思维_哔哩哔哩_bilibili
4.Observable使用
Angular7知识点5----Observable(可观察对象)_暖一杯茶的博客-CSDN博客
5.Retrofit讲解
网络请求(三)— Retrofit_橙子19911016的博客-CSDN博客_retrofit网络请求^v63^js_top,201^v3^control_1,213^v2^t3_esquery_v1&spm=1018.2226.3001.4187
6.RXJava执行顺序
RxJava在Android中的使用详解_AndyYuan317的博客-CSDN博客_rxjava android^v63^js_top,201^v3^control_1,213^v2^t3_esquery_v1&spm=1018.2226.3001.4187
Retrofit的基本使用流程:
1) 通过建造者模式构建一个Retrofit实例;
2) 通过Retrofit对象的create方法创建接口实例(动态代理);
3) 调用接口的方法解析注解,调用具体的网络请求方法;
4) 通过数据解析器解析数据;
5) 调用回调执行器,切换线程,处理返回结果;
添加依赖(Build.gradle)
//RxJava的依赖包
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
//RxAndroid的依赖包
implementation 'io.reactivex.rxjava3:rxjava:3.0.0'
/*retrofit2依赖包*/
implementation 'com.squareup.retrofit2:retrofit:2.7.0'
//配合Rxjava 使用的适配器
implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0'
//依赖和retrofit对应的gson解析类库,配置了就拥有了json解析的功能
implementation 'com.squareup.retrofit2:converter-gson:2.0.2'
/*okhttp3依赖*/
implementation 'com.squareup.okhttp3:okhttp:3.1.2'
添加网络请求权限(AndroidManifest.xml)
创建接口DownloadService.java
package com.example.rxjavastudy1;
import io.reactivex.rxjava3.core.Observable;
import okhttp3.ResponseBody;
import retrofit2.http.GET;
import retrofit2.http.Streaming;
import retrofit2.http.Url;
public interface DownloadService {
@GET
//GET下载文件必须结合@Streaming使用
@Streaming
/*ResponseBody是抽象类,它实例化的那部分它封装进去了在源码里
后续我们只需要直接在mainActivity直接调用,通过string()字符流的方式读取内容,
bytes()字节流的方式读取内容
我们还可以获得字节流,实现自己的定制化读取。*/
Observable download(@Url String fileUrl);
//Observable属于RxJS库里面的一个对象,可以用来处理异步事件
}
样式ui编写(activityMain.xml)
MainActivity.java编写
package com.example.rxjavastudy1;
import androidx.appcompat.app.AppCompatActivity;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import java.io.PrintWriter;
import java.io.StringWriter;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.annotations.NonNull;
import io.reactivex.rxjava3.core.Observer;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.functions.Function;
import io.reactivex.rxjava3.schedulers.Schedulers;
import okhttp3.ResponseBody;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
public class MainActivity extends AppCompatActivity {
/*ImageView控件,用来显示结果图像*/
private ImageView image;
/*创建接口对象*/
DownloadService downloadService;
/*创建弹窗对象*/
ProgressDialog progressDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
image = findViewById(R.id.image);
}
/*图片显示加载功能*/
public void showImageAction(View view) {
//1.创建Retrofit对象
Retrofit retrofit = new Retrofit.Builder()
// 设置 网络请求 Url
.baseUrl("http://baidu.com/")
/*添加rxjava适配*/
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
//设置使用Gson解析(记得加入依赖),定义转换器
.addConverterFactory(GsonConverterFactory.create())
.build();
/*2.接口实例化*/
downloadService = retrofit.create(DownloadService.class);
/*3.调用接口方法下载一张图片*/
downloadService.download("https://c-ssl.duitang.com/uploads/blog/202208/11/20220811225937_06f91.jpg")
/*给上面分配异步线程,实现图片下载操作*/
.subscribeOn(Schedulers.io())
/*2.进行需求转换*/
/*需求1:进行图片格式转换*/
/*尖括号第一个是传进来的参数格式,第二个是传出去的文件格式*/
.map(new Function() {
@Override
public Bitmap apply(ResponseBody path) throws Exception {
/*Byte[]类型转为Inputstream流*/
Bitmap bitmap;
//解流
bitmap = BitmapFactory.decodeStream(path.byteStream());
//传给下个流或者onnext方法
return bitmap;
}
})
/*需求2:加水印*/
/*尖括号第一个是传进来的参数格式,第二个是传出去的文件格式*/
.map(new Function() {
@Override
public Bitmap apply(Bitmap bitmap) throws Throwable {
//创建方法对象
Paint paint = new Paint();
//设置水印颜色
paint.setColor(Color.YELLOW);
//设置水印字体大小
paint.setTextSize(100);
//设置水印文本,位置信息
Bitmap shuiyinBitmap = drawTextToBitmap(bitmap, "你瞅啥", paint, 88, 88);
//传给下个流或者onnext方法
return shuiyinBitmap;
}
})
//在android主线程中展示
.observeOn(AndroidSchedulers.mainThread())
/*观察者*/
.subscribe(new Observer() {
/*1.订阅*/
/*订阅事件disposable*/
/*OnSubscribe 会被存储在返回的 Observable 对象中,它的作用相当于一个计划表,
当 Observable 被订阅的时候,OnSubscribe 的 call() 方法会自动被调用,事件序列就会依照设定依次触发*/
@Override
public void onSubscribe(@NonNull Disposable d) {
/*创建弹窗对象*/
progressDialog = new ProgressDialog(MainActivity.this);
/*设置弹窗信息*/
progressDialog.setTitle("RXJava 玩儿命加载中。。。");
progressDialog.show();
}
/*3.*/
@Override
public void onNext(@NonNull Bitmap pic) {
/*展示图片*/
image.setImageBitmap(pic);
}
/*如果出现报错就会执行这一条*/
@Override
public void onError(@NonNull Throwable e) {
StringWriter stringWriter = new StringWriter();
e.printStackTrace(new PrintWriter(stringWriter));
/*打印错误信息*/
Log.d("tag", stringWriter.toString());
}
/*4.整个链条全部结束*/
@Override
public void onComplete() {
/*隐藏加载框*/
progressDialog.dismiss();
}
});
}
/*加水印后的bitmap方法*/
private final Bitmap drawTextToBitmap(Bitmap bitmap, String text, Paint paint, int paddingLeft, int paddingTop) {
Bitmap.Config bitmapConfig = bitmap.getConfig();
paint.setDither(true);
paint.setFilterBitmap(true);
if (bitmapConfig == null) {
bitmapConfig = Bitmap.Config.ARGB_8888;
}
bitmap = bitmap.copy(bitmapConfig, true);
Canvas canvas = new Canvas(bitmap);
canvas.drawText(text, paddingLeft, paddingTop, paint);
return bitmap;
}
}
小费同学也是Android学习中,参考了很多大佬的讲解,如果有描述不对的地方请各位同学多多指正,希望我们可以在不断努力专注学习安卓中技术水平越来越厉害~