Android - 网络请求之 Retrofit2 + RxJa

作者: Allens_Jiang | 来源:发表于2017-12-28 19:17 被阅读282次
    老婆保佑,代码无BUG

    目录

    • 引用
    • 与其他开源请求库对比
    • Retrofit注解
    • 使用
      • GET请求
      • POST请求
    • Retrofit2 + RxJava
      • 基础使用
      • 优化
      • 封装Retrofit2 + RxJava

    一:引用

    retrofit 官网

    compile 'com.squareup.retrofit2:retrofit:2.3.0'
    

    二:与其他开源请求库对比

    image

    三:Retrofit注解

    四:使用

    GET请求

    (1) 定义接口

    
    public interface ApiService {
        @GET
        Call<ResponseBody> getGetData(@Url String url);
        
        //Get请求,方法中指定@Path参数和@Query参数
        //@path参数用于替换url中{}的部分,
        //@Query将在url地址中追加类似"page=1"的字符串
        @GET("{mobile}/get?") 
        Call<ResponseBody> getPathData(@Path("mobile") String mobile, @Query("phone") String phone, @Query("key") String key);
    
        @GET("mobile/get?")
        Call<ResponseBody> getQueryMapData(@QueryMap Map<String, String> map);
    
    }
    

    (2) Activity

        public void btnYS(View view) {
            String baseUrl = "http://apis.juhe.cn/";
            String url = baseUrl + "mobile/get?phone=18856907654&key=5778e9d9cf089fc3b093b162036fc0e1";
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(baseUrl)
                    .build();
            ApiService apiService = retrofit.create(ApiService.class);
            
            //第一种
            Call<ResponseBody> call = apiService.getGetData(url);
            
            //第二种
            HashMap<String, String> map = new HashMap<>();
            map.put("phone", "18856907654");
            map.put("key", "5778e9d9cf089fc3b093b162036fc0e1");
            Call<ResponseBody> call = apiService.getQueryMapData(map);
            
            //第三种
            apiService.getPathData("mobile","18856907654","5778e9d9cf089fc3b093b162036fc0e1");
            
            
            
            call.enqueue(new Callback<ResponseBody>() {
                @Override
                public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                    //主线程
                    try {
                        Logger.e("response---->" + response.body().string());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
    
                @Override
                public void onFailure(Call<ResponseBody> call, Throwable t) {
                    Logger.e("Throwable---->" + t.getMessage());
                }
            });
        }
    
    

    POST请求

    (1) 定义接口

    public interface ApiService {
        @FormUrlEncoded
        @POST("mobile/get")  //注意  不是 /  结束
        Call<ResponseBody> postFile(@Field("phone") String phone,
                                    @Field("key") String key);
                                    
        @FormUrlEncoded
        @POST("mobile/get")  //注意  不是 /  结束
        Call<ResponseBody> postFile(@FieldMap Map<String,String> map);
    }
    

    (2) Activity

        public void btnPostFile(View view) {
            String baseUrl = "http://apis.juhe.cn/";
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(baseUrl)
                    .build();
            ApiService apiService = retrofit.create(ApiService.class);
            
            //第一种
            Call<ResponseBody> call = apiService.postFile("18856907654", "5778e9d9cf089fc3b093b162036fc0e1");
            
            //第二种
            HashMap<String, String> map = new HashMap<>();
            map.put("phone", "18856907654");
            map.put("key", "5778e9d9cf089fc3b093b162036fc0e1");
            Call<ResponseBody> call = apiService.postFile(map);
             //省略一下代码
        }
    

    以上讲的都是废话,哈哈下面才是正确的打开放式


    Retrofit2 + RxJava

    引入 依赖

    //Retrofit2
    compile 'com.squareup.retrofit2:retrofit:2.3.0'
    //RxJava
    compile 'io.reactivex.rxjava2:rxjava:2.1.7'
    //RxAndroid
    compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
    //Retrofit 支持Rxjava 的支持库
    compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
    
    

    先导入,然后慢慢说,这些都是干啥的

    按套路出牌,肯定先写接口

    public interface ApiService {
        @GET
        Observable<ResponseBody> getGetData(@Url String url);
    }
    

    看到这,就有兄弟说了,哥们你这里写错了,不应该是Observable应该是Call

    u=1804519813,2654766997&fm=27&gp=0.jpg

    都说了 之前说的都是屁话,这才是正确的打开方式,我们使用的是Observable,RxJava ,都是这么玩的 哈哈

    so 继续

    Activity 先来一个看看

    package com.allens.retrofitdemo;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    
    import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
    
    import io.reactivex.Observer;
    import io.reactivex.android.schedulers.AndroidSchedulers;
    import io.reactivex.disposables.Disposable;
    import io.reactivex.functions.Consumer;
    import io.reactivex.schedulers.Schedulers;
    import okhttp3.ResponseBody;
    import retrofit2.Retrofit;
    
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            String baseUrl = "http://apis.juhe.cn/";
            String url = baseUrl + "mobile/get?phone=18856907654&key=5778e9d9cf089fc3b093b162036fc0e1";
    
    
            // 设置网络请求的Url地址
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl("http://fanyi.youdao.com/")
                    // 支持RxJava平台
                    //compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'   是他 就是他 
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .build();
    
            retrofit.create(ApiService.class)
                    .getGetData(url)//注意看,这里返回的对象时什么,和原生的返回不同,也是我们把上面接口改的原因
                    //在子线程取数据
                    .subscribeOn(Schedulers.io())
                    .unsubscribeOn(Schedulers.io())
                    //在主线程显示ui 
                    // compile 'io.reactivex.rxjava2:rxandroid:2.0.1'  这个库下才有AndroidSchedulers.mainThread
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Observer<ResponseBody>() {
                        @Override
                        public void onSubscribe(Disposable d) {
                            
                        }
    
                        @Override
                        public void onNext(ResponseBody responseBody) {
    
                        }
    
                        @Override
                        public void onError(Throwable e) {
    
                        }
    
                        @Override
                        public void onComplete() {
    
                        }
                    });
    
        }
    }
    

    是不是感觉很简单。哈哈,对就是这么简单。Post 请求也这么玩,其他都不变,改一下接口,改成 Observable,然后使用RxJava 切换线程就哦了,

    如果只是这种程度你就满足了,哈哈,大兄弟,你也太容易了,

    其实我们还可以这么玩


    五:优化

    1. 设置数据解析器

    (1)添加一条依赖

    //gson 解析器
    compile 'com.squareup.retrofit2:converter-gson:2.3.0'
    

    修改接口

    public interface ApiService {
        @GET
        Observable<Bean> getGetData(@Url String url);
    }
    

    找不同,哈哈 原来的是ResponseBody,现在是Bean,至于Bean 是什么,Bean 对象啊,大兄弟,这个不知道的话,表示。。。。

    修改一下Activity中的代码

    Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl("http://fanyi.youdao.com/")
                    // 设置数据解析器
                    .addConverterFactory(GsonConverterFactory.create()) 
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .build();
    retrofit.create(ApiService.class)
                    .getGetData(url)
                    .subscribeOn(Schedulers.io())
                    .unsubscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Observer<Bean>() {
                        @Override
                        public void onSubscribe(Disposable d) {
    
                        }
    
                        @Override
                        public void onNext(Bean bean) {
    
                        }
    
                        @Override
                        public void onError(Throwable e) {
    
                        }
    
                        @Override
                        public void onComplete() {
    
                        }
                    });
    

    可以看到,原来返回的是ResponseBody,现在返回的是已经解析成功的Bean 对象,

    关于数据解析器(Converter)

    • Retrofit支持多种数据解析方式
    • 使用时需要在Gradle添加依赖
    数据解析器 Gradle依赖
    Gson com.squareup.retrofit2:converter-gson:2.0.2
    Jackson com.squareup.retrofit2:converter-jackson:2.0.2
    Simple XML com.squareup.retrofit2:converter-simplexml:2.0.2
    Protobuf com.squareup.retrofit2:converter-protobuf:2.0.2
    Moshi com.squareup.retrofit2:converter-moshi:2.0.2
    Wire com.squareup.retrofit2:converter-wire:2.0.2
    Scalars com.squareup.retrofit2:converter-scalars:2.0.2

    网络请求适配器(CallAdapter)

    还记得compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0' 么,他其实就是一个网络请求适配器
    使用时如使用的是 Android 默认的 CallAdapter,则不需要添加网络请求适配器的依赖,否则则需要按照需求进行添加
    Retrofit 提供的 CallAdapter
    使用时需要在Gradle添加依赖:

    网络请求适配器 Gradle依赖 备注
    guava com.squareup.retrofit2:adapter-guava:2.0.2 没用过
    Java8 com.squareup.retrofit2:adapter-java8:2.0.2 没用过
    rxjava com.squareup.retrofit2:adapter-rxjava:2.0.2 retrofit现在只支持到rxjava1.XX
    rxjava com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0. 大神写的这个库可以支持到rxjava2.X

    到这里就是不是就感觉,人生圆满了呢,哈哈
    还有后招呢,现在我想把服务端返回的数据全部打印出来,怎么做呢

    u=1379330171,3486067710&fm=27&gp=0.jpg

    2.加入拦截器

    (1)导入库

    compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'
    

    (2)初始化HttpLoggingInterceptor

    HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
                @Override
                public void log(String message) {
                    //打印retrofit日志
                    Log.i("RetrofitLog","retrofitBack = "+message);
                }
            });
            loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
    

    (3)配置okhttp

    client = new OkHttpClient.Builder()
                        .addInterceptor(loggingInterceptor)
                        .connectTimeout(mTimeOut, TimeUnit.SECONDS)
                        .readTimeout(mTimeOut, TimeUnit.SECONDS)
                        .writeTimeout(mTimeOut, TimeUnit.SECONDS)
                        .build();
    

    然后嘛,

    就可以在控制台看到请求的Log啦

    12-28 04:29:07.337 3922-3944/com.allens.test E/XRetrofit: retrofitBack -> <-- 200 OK http://devapi.water.com/Oauth/authorize (185ms)
    12-28 04:29:07.337 3922-3944/com.allens.test E/XRetrofit: retrofitBack -> Date: Thu, 28 Dec 2017 09:29:10 GMT
    12-28 04:29:07.337 3922-3944/com.allens.test E/XRetrofit: retrofitBack -> Server: Apache/2.4.17 (Win64) OpenSSL/1.0.2d PHP/5.6.16
    12-28 04:29:07.337 3922-3944/com.allens.test E/XRetrofit: retrofitBack -> X-Powered-By: PHP/5.6.16
    12-28 04:29:07.337 3922-3944/com.allens.test E/XRetrofit: retrofitBack -> Content-Length: 104
    12-28 04:29:07.337 3922-3944/com.allens.test E/XRetrofit: retrofitBack -> Keep-Alive: timeout=5, max=100
    12-28 04:29:07.337 3922-3944/com.allens.test E/XRetrofit: retrofitBack -> Connection: Keep-Alive
    12-28 04:29:07.337 3922-3944/com.allens.test E/XRetrofit: retrofitBack -> Content-Type: application/json; charset=utf-8
    12-28 04:29:07.338 3922-3944/com.allens.test E/XRetrofit: retrofitBack -> 
    12-28 04:29:07.338 3922-3944/com.allens.test E/XRetrofit: retrofitBack -> {"is_success":true,"result":{"code":"9405f14110770bf8bd09d1397173e382eab923b19820b9330ce7d533cb3d4722"}}
    12-28 04:29:07.338 3922-3944/com.allens.test E/XRetrofit: retrofitBack -> <-- END HTTP (104-byte body)
    

    六: 最后在优化

    哈哈,自己封装了一下,有兴趣的小伙伴可以点击查看,及使用

    XRetrofit ,点击查看如何使用

    相关文章

      网友评论

      本文标题:Android - 网络请求之 Retrofit2 + RxJa

      本文链接:https://www.haomeiwen.com/subject/gsivgxtx.html