Retrofit 和 Rxjava 的簡單實用

   最近在整理 Retrofit 和 Rxjava 的知識,前面幾篇文章分別整理了 Rxjava 和  Retrofit 現在就來整理一下 Retrofit 和 Rxjava的連用。知道了Retrofit 和 Rxjava 的單獨用法,連用其實很簡單。在Retrofit的基礎上改。

不一樣的地方有如下幾點:

第一,導的包不一樣

Retrofit中:

    compile 'com.squareup.retrofit2:retrofit:2.2.0'// Retrofit庫
    compile 'com.squareup.retrofit2:converter-gson:2.3.0'//返回的數據是json的,用到了gson解析

Retrofit 和 Rxjava連用中

    implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'
    implementation 'io.reactivex.rxjava2:rxjava:2.x.y'
    implementation 'com.squareup.retrofit2:converter-gson:2.3.0'//轉換器,請求結果轉換成Model
    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'//配合Rxjava 使用

第二,創建用於 描述網絡請求的接口的時候,方法返回值類型的改變。由Retrofit中的 Call<T> 變成了 Observable<T>,代碼如下:

Retrofit中:

/**
 *   創建 用於描述網絡請求 的接口
 *   Retrofit將 Http請求 抽象成 Java接口:採用 註解 描述網絡請求參數 和配置網絡請求參數
 */
public interface ApiService {
    //測試 get
    @GET("ajax.php?a=fy&f=auto&t=auto&w=hello")
    Call<ResponseInfo> testGet();

    //測試 post
    @POST("ajax.php?a=fy&f=auto&t=auto")
    Call<ResponseInfo> testPost(@Query("w") String w);

    //測試 下載文件
    @Streaming
    @GET
    Call<ResponseBody> testDownload(@Url String fileUrl);
}

Retrofit 和 Rxjava連用中

/**
 *   創建 用於描述網絡請求 的接口
 *   Retrofit將 Http請求 抽象成 Java接口:採用 註解 描述網絡請求參數 和配置網絡請求參數
 */
public interface ApiService {
    //測試 get
    @GET("ajax.php?a=fy&f=auto&t=auto&w=hello")
    Observable<ResponseInfo> testGet();

    //測試 post
    @POST("ajax.php?a=fy&f=auto&t=auto")
    Observable<ResponseInfo> testPost(@Query("w") String w);

    //測試 下載文件
    @Streaming
    @GET
    Observable<ResponseBody> testDownload(@Url String fileUrl);
}

第三,創建Retrofit實例的時候需要加上addCallAdapterFactory(RxJava2CallAdapterFactory.create()),代碼如下。

      Retrofit中:

  retrofit = new Retrofit.Builder()
                .baseUrl("http://fy.iciba.com/") // 設置 網絡請求 Url
                .addConverterFactory(GsonConverterFactory.create()) //設置使用Gson解析(記得加入依賴)
                .build();

      Retrofit 和 Rxjava連用中:

 retrofit = new Retrofit.Builder()
                .baseUrl("http://fy.iciba.com/") // 設置 網絡請求 Url
                .addConverterFactory(GsonConverterFactory.create()) //設置使用Gson解析(記得加入依賴)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();

第三,網絡請求方式不一樣

Retrofit中:

        ApiService request = retrofit.create(ApiService.class);
        Call<ResponseInfo> call = request.testGet();// 封裝請求
        call.enqueue(new Callback<ResponseInfo>() {// 發送網絡請求(異步)
            @Override
            public void onResponse(Call<ResponseInfo> call, Response<ResponseInfo> response) {//主線程中調用
                ResponseInfo body = response.body();
                Log.i("gao", "測試  get body = " + body + "  線程名字 = " + Thread.currentThread().getName());
                Toast.makeText(MainActivity.this, "測試GET= " + body.content.word_mean.get(0), Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onFailure(Call<ResponseInfo> call, Throwable t) {//主線程中調用
                Log.i("gao", " testGet onFailure " + "  線程名字 = " + Thread.currentThread().getName());
                Toast.makeText(MainActivity.this, " testGet onFailure ", Toast.LENGTH_SHORT).show();
            }
        });

Retrofit 和 Rxjava連用中:

        ApiService request = retrofit.create(ApiService.class);
        Observable<ResponseInfo> observable = request.testGet();// 封裝請求
        observable.subscribeOn(Schedulers.io())//網絡請求發生在 子線程
                .observeOn(AndroidSchedulers.mainThread())//請求回調發生在 主線程
                .subscribe(new Observer<ResponseInfo>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(ResponseInfo responseInfo) {
                        Log.i("gao", "測試  get body = " + responseInfo + "  線程名字 = " + Thread.currentThread().getName());
                        Toast.makeText(MainActivity.this, "測試GET= " + responseInfo.content.word_mean.get(0), Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.i("gao", " testGet onFailure " + "  線程名字 = " + Thread.currentThread().getName());
                Toast.makeText(MainActivity.this, " testGet onFailure ", Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onComplete() {

                    }
                });

demo中和上篇文章一樣寫了 怎麼請求 get  post  和 怎麼下載文件,的方法,這裏是MainActivity的代碼。如果需要完整的代碼,在博客的最後有下載的方法。

import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import okhttp3.ResponseBody;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

public class MainActivity extends Activity implements View.OnClickListener {
    Retrofit retrofit;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.testGet).setOnClickListener(this);
        findViewById(R.id.testPost).setOnClickListener(this);
        findViewById(R.id.testLoaddown).setOnClickListener(this);

        // 創建Retrofit實例時需要通過Retrofit.Builder,並調用baseUrl方法設置URL。Retrofit2的baseUlr 必須以 /(斜線)結束,不然會拋出一個IllegalArgumentException
        retrofit = new Retrofit.Builder()
                .baseUrl("http://fy.iciba.com/") // 設置 網絡請求 Url
                .addConverterFactory(GsonConverterFactory.create()) //設置使用Gson解析(記得加入依賴)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();

        //動態獲取權限
        AppPermission.isGrantExternalRW(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.testGet:
                testGet();

                break;
            case R.id.testPost:
                testPost("hello");
                break;

            case R.id.testLoaddown:
                if (AppPermission.isGrantExternalRW(this)) {
                    String url = "http://imtt.dd.qq.com/16891/89E1C87A75EB3E1221F2CDE47A60824A.apk?fsname=com.snda.wifilocating_4.2.62_3192.apk&csr=1bbd";
                    testLoaddown(Environment.getExternalStorageDirectory() + "/ceshi.apk", url);
                }
                break;
        }
    }

    public void testGet() {
        ApiService request = retrofit.create(ApiService.class);
        Observable<ResponseInfo> observable = request.testGet();// 封裝請求
        observable.subscribeOn(Schedulers.io())//網絡請求發生在 子線程
                .observeOn(AndroidSchedulers.mainThread())//請求回調發生在 主線程
                .subscribe(new Observer<ResponseInfo>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(ResponseInfo responseInfo) {
                        Log.i("gao", "測試  get body = " + responseInfo + "  線程名字 = " + Thread.currentThread().getName());
                        Toast.makeText(MainActivity.this, "測試GET= " + responseInfo.content.word_mean.get(0), Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.i("gao", " testGet onFailure " + "  線程名字 = " + Thread.currentThread().getName());
                        Toast.makeText(MainActivity.this, " testGet onFailure ", Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

    public void testPost(String string) {
        ApiService request = retrofit.create(ApiService.class);
        Observable<ResponseInfo> observable = request.testPost(string);// 封裝請求
        observable.subscribeOn(Schedulers.io())//網絡請求在子線程
                .observeOn(AndroidSchedulers.mainThread())//請求回調在主線程
                .subscribe(new Observer<ResponseInfo>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(ResponseInfo responseInfo) {
                        Log.i("gao", "測試  post body = " + responseInfo + "  線程名字 = " + Thread.currentThread().getName());
                        Toast.makeText(MainActivity.this, "測試  post body = " + responseInfo, Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.i("gao", "testPost onFailure " + "  線程名字 = " + Thread.currentThread().getName());
                        Toast.makeText(MainActivity.this, "testPost onFailure ", Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

    public void testLoaddown(final String path, String url) {
        Retrofit retrofitLoaddown = new Retrofit.Builder()
                .baseUrl("http://imtt.dd.qq.com/")
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
        ApiService request = retrofitLoaddown.create(ApiService.class);
        Observable<ResponseBody> observable = request.testDownload(url);//當你填進去的url是完整url的時候,設置的baseurl是無效的
        observable.subscribeOn(Schedulers.io())
                .observeOn(Schedulers.io())
                .subscribe(new Observer<ResponseBody>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(ResponseBody responseBody) {
                        Log.i("gao", "測試    線程名字 = " + Thread.currentThread().getName());
                        //將Response寫入到從磁盤中,詳見下面分析   注意,這個方法是運行在子線程中的
                        writeResponseToDisk(path, responseBody);
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.i("gao", "testLoaddown 網絡錯誤~ " + "  線程名字 = " + Thread.currentThread().getName());
                        Toast.makeText(MainActivity.this, "testLoaddown 網絡錯誤~ ", Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

    private void writeResponseToDisk(String path, ResponseBody responseBody) {
        //從response獲取輸入流以及總大小
        writeFileFromIS(new File(path), responseBody.byteStream(), responseBody.contentLength());
    }

    private static int sBufferSize = 8192;

    //將輸入流寫入文件
    private void writeFileFromIS(File file, InputStream is, long totalLength) {

        //創建文件
        if (!file.exists()) {
            if (!file.getParentFile().exists())
                file.getParentFile().mkdir();
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
                Log.i("gao", "創建文件錯誤~ " + "  線程名字 = " + Thread.currentThread().getName());
            }
        }

        OutputStream os = null;
        long currentLength = 0;
        try {
            os = new BufferedOutputStream(new FileOutputStream(file));
            byte data[] = new byte[sBufferSize];
            int len;
            while ((len = is.read(data, 0, sBufferSize)) != -1) {
                os.write(data, 0, len);
                currentLength += len;
                //計算當前下載進度
                Log.i("gao", "下載 進度 = " + (int) (100 * currentLength / totalLength));
            }
            //下載完成,並返回保存的文件路徑
            Log.i("gao", "下載完成 file.getAbsolutePath() = " + file.getAbsolutePath());
        } catch (IOException e) {
            e.printStackTrace();
            Log.i("gao", "下載失敗");
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (os != null) {
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

 

有什麼不明白的可以看我上篇文章,Retrofit的簡單實用(get post 下載文件),裏面詳細的介紹了怎麼使用Rrtrofit。

文章用到的代碼可以去這裏下載  資源。歡迎大家評論,溝通。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章