天天看点

RXJava3+OKHTTP3+Retrofit2(观察者设计模式)讲解+实战完整代码(okhttp3+rxjava3+retrofit2结合)

废话不多说,全部代码请拉到最后!!!!

retrofit是载体(基于okhttp),rxjava 就是一个实现异步操作的库。 它的简洁的与众不同之处在于,随着程序逻辑变得越来越复杂,它依然能够保持简洁。

就比如我们开了一家披萨店:

你总不能直接把披萨胚直接卖给客人

RXJava3+OKHTTP3+Retrofit2(观察者设计模式)讲解+实战完整代码(okhttp3+rxjava3+retrofit2结合)

RX思维分析(完成披萨订单)

被观察者(起点)-------需求(1个或者多个)---------观察者(终点)

就是和卖批萨一样,一条流水线,你开始是个被观察者(披萨胚),观察者(客人)点餐提出需求,通过中间做这些需求(放芝士啥的)最后一个需求结束以后把参数(披萨成品)传给观察者(客人)

RX=反应式 reactive x==反应式==响应式编程思维RX == 响应式编程思维 什么是响应式编程? 答:根据上一层的响应来影响下一层的变化 (起点〉点击按钮触发方法---->请求服务器---->服务器的响应.---->解析响应的json数据界面展示出来(终点)

RXJava3+OKHTTP3+Retrofit2(观察者设计模式)讲解+实战完整代码(okhttp3+rxjava3+retrofit2结合)

(1)项目实战环节:RXJava3+OKHTTP3

1.编写样式,并在按钮加一个自定义命名onclick事件

RXJava3+OKHTTP3+Retrofit2(观察者设计模式)讲解+实战完整代码(okhttp3+rxjava3+retrofit2结合)
RXJava3+OKHTTP3+Retrofit2(观察者设计模式)讲解+实战完整代码(okhttp3+rxjava3+retrofit2结合)

2.因为是加载网络图片,所以要manifest中开启网络权限

RXJava3+OKHTTP3+Retrofit2(观察者设计模式)讲解+实战完整代码(okhttp3+rxjava3+retrofit2结合)

3.添加RXJava 3X依赖才能正常在mainActivity调用方法

RXJava3+OKHTTP3+Retrofit2(观察者设计模式)讲解+实战完整代码(okhttp3+rxjava3+retrofit2结合)

4.编写MainActivity.java代码

RXJava3+OKHTTP3+Retrofit2(观察者设计模式)讲解+实战完整代码(okhttp3+rxjava3+retrofit2结合)
RXJava3+OKHTTP3+Retrofit2(观察者设计模式)讲解+实战完整代码(okhttp3+rxjava3+retrofit2结合)
RXJava3+OKHTTP3+Retrofit2(观察者设计模式)讲解+实战完整代码(okhttp3+rxjava3+retrofit2结合)
RXJava3+OKHTTP3+Retrofit2(观察者设计模式)讲解+实战完整代码(okhttp3+rxjava3+retrofit2结合)
RXJava3+OKHTTP3+Retrofit2(观察者设计模式)讲解+实战完整代码(okhttp3+rxjava3+retrofit2结合)
RXJava3+OKHTTP3+Retrofit2(观察者设计模式)讲解+实战完整代码(okhttp3+rxjava3+retrofit2结合)
RXJava3+OKHTTP3+Retrofit2(观察者设计模式)讲解+实战完整代码(okhttp3+rxjava3+retrofit2结合)

效果图:

RXJava3+OKHTTP3+Retrofit2(观察者设计模式)讲解+实战完整代码(okhttp3+rxjava3+retrofit2结合)

因为是异步,所以肯定不止一个需求,那么接下来我们再添加一个

RXJava3+OKHTTP3+Retrofit2(观察者设计模式)讲解+实战完整代码(okhttp3+rxjava3+retrofit2结合)

就只需要在map后面加需求就好了

先去自定义了一个方法,然后再调用它

RXJava3+OKHTTP3+Retrofit2(观察者设计模式)讲解+实战完整代码(okhttp3+rxjava3+retrofit2结合)
RXJava3+OKHTTP3+Retrofit2(观察者设计模式)讲解+实战完整代码(okhttp3+rxjava3+retrofit2结合)

效果图:

RXJava3+OKHTTP3+Retrofit2(观察者设计模式)讲解+实战完整代码(okhttp3+rxjava3+retrofit2结合)

(2)项目实战环节:Retrofit2+RXJava3+OKHTTP3结合( Retrofit本身并不具备网络请求的能力 ):

Retrofit是一个网络请求框架的封装,底层网络请求默认使用OkHttp,也就是说Retrofit本身并不具备网络请求的能力,只是简化了网络请求的相关参数配置或者说Retrofit只负责上层接口的封装。

使用Retrofit,实际上是使用Retrofit接口层封装请求参数、Header、Url 等信息,之后由OkHttp完成后续的请求操作,当服务端返回数据之后,OkHttp再将原始的结果交给Retrofit,然后Retrofit根据用户的需求,对结果进行解析。

1.导入retrofit依赖

RXJava3+OKHTTP3+Retrofit2(观察者设计模式)讲解+实战完整代码(okhttp3+rxjava3+retrofit2结合)

2.创建接口,这里只是定义rxjava的observable方法,@Url注解后面传入图片链接,ResponseBody是抽象类,它实例化的那部分它封装进去了在源码里后续我们只需要直接在mainActivity直接调用,通过string()字符流的方式读取内容,bytes()字节流的方式读取内容我们还可以获得字节流,实现自己的定制化读取。会在mainActivity写。

RXJava3+OKHTTP3+Retrofit2(观察者设计模式)讲解+实战完整代码(okhttp3+rxjava3+retrofit2结合)

在原有的基础上改一下,首先在mainActivity创建接口对象,进行实例化

下面我们可以看见map里面okhttp在结合rxjava的时候不写接口,进行请求图片的时候需要写很多行代码,各种调用方法赋值。很繁琐。。。

RXJava3+OKHTTP3+Retrofit2(观察者设计模式)讲解+实战完整代码(okhttp3+rxjava3+retrofit2结合)

3.Retrofit实例化

RXJava3+OKHTTP3+Retrofit2(观察者设计模式)讲解+实战完整代码(okhttp3+rxjava3+retrofit2结合)

4.创建网络请求接口对象实例

RXJava3+OKHTTP3+Retrofit2(观察者设计模式)讲解+实战完整代码(okhttp3+rxjava3+retrofit2结合)

5.编写map需求(关于下载下来的文件流格式转换这一块)这个需求完成(加工完成)以后会将bitmap图片传给观察者(客人)里面的onNext()方法。如果要是有别的需求,会把bitmap图片传到下一个需求,只有把需求全部完成才会传给onNext()方法。

RXJava3+OKHTTP3+Retrofit2(观察者设计模式)讲解+实战完整代码(okhttp3+rxjava3+retrofit2结合)
RXJava3+OKHTTP3+Retrofit2(观察者设计模式)讲解+实战完整代码(okhttp3+rxjava3+retrofit2结合)

在onnext我们也可以除了展示做其他操作,这里就只写了一个展示功能,onnext执行完成以后如果成功跑完,就会执行complete方法,弹窗隐藏,如果期间我们点击了别的地方啥的导致无法正常跑完就会执行onError报错。

RXJava3+OKHTTP3+Retrofit2(观察者设计模式)讲解+实战完整代码(okhttp3+rxjava3+retrofit2结合)

周期梳理:

RXJava3+OKHTTP3+Retrofit2(观察者设计模式)讲解+实战完整代码(okhttp3+rxjava3+retrofit2结合)
RXJava3+OKHTTP3+Retrofit2(观察者设计模式)讲解+实战完整代码(okhttp3+rxjava3+retrofit2结合)

效果图:

RXJava3+OKHTTP3+Retrofit2(观察者设计模式)讲解+实战完整代码(okhttp3+rxjava3+retrofit2结合)

学习期间疑惑点解答:

RXJava3+OKHTTP3+Retrofit2(观察者设计模式)讲解+实战完整代码(okhttp3+rxjava3+retrofit2结合)

参考文档:

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) 调用回调执行器,切换线程,处理返回结果;

完整代码(okhttp3+rxjava3+retrofit2结合)

添加依赖(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)

<!--开启网络权限-->
    <uses-permission android:name="android.permission.INTERNET"/>
           

创建接口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<ResponseBody> download(@Url String fileUrl);
    //Observable属于RxJS库里面的一个对象,可以用来处理异步事件
}
           

样式ui编写(activityMain.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >
    <!--按钮触发-->
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="showImageAction"
        android:text="图片显示加载功能"
        tools:ignore="HardcodedText,UsingOnClickInXml" />
    <!--RXJava来显示我们的图片-->
    <ImageView
        android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>
           

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<ResponseBody, Bitmap>() {
                    @Override
                    public Bitmap apply(ResponseBody path) throws Exception {
                        /*Byte[]类型转为Inputstream流*/
                        Bitmap bitmap;
                        //解流
                        bitmap = BitmapFactory.decodeStream(path.byteStream());
                        //传给下个流或者onnext方法
                        return bitmap;
                    }
                })
                /*需求2:加水印*/
                /*尖括号第一个是传进来的参数格式,第二个是传出去的文件格式*/
                .map(new Function<Bitmap, Bitmap>() {
                    @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<Bitmap>() {
                    /*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学习中,参考了很多大佬的讲解,如果有描述不对的地方请各位同学多多指正,希望我们可以在不断努力专注学习安卓中技术水平越来越厉害~