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。

文章用到的代码可以去这里下载  资源。欢迎大家评论,沟通。

 

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