天天看點

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學習中,參考了很多大佬的講解,如果有描述不對的地方請各位同學多多指正,希望我們可以在不斷努力專注學習安卓中技術水準越來越厲害~