Retrofit 2.0 应用场景概述

最近最火的网络库应该是Retrofit了,我也在项目中耍了起来,可以说是非常的有趣。
个人感觉是Retrofit网络库是简洁,实用和逻辑清晰,将网络接口和回调逻辑分层处理,在逻辑层你都可以不用知道网络接口的类型和参数。

我就开始从自己的应用场景说起吧。

Retrofit 2.0 接入

首先,我们应该是添加依赖,这应该大家都很熟悉吧,我就添加了我项目中需要用的依赖。

    compile 'com.squareup.retrofit2:retrofit:2.1.0'
    compile 'com.squareup.retrofit2:converter-gson:2.1.0'
    compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'

添加了这三个依赖我们就可以正常的耍起来了,当然如果你要用rxJava别忘了添加相关依赖,这里我就不说了。

1.先把RetrofitClient搞起来

我们要先知道Retrofit其实一个对okhttp的一个封装,它是基于okhttp的,所以okhttp的有些特性也可以使用。不多说,我们先把Retrofit封装起来使用。

首先,我们需要定义一个网络请求的接口,它是负责写所有网络请求的,需要根据Retrofit的规范来写,待会下面会详细说。

//Retrofit 网络请求接口
public interface RetrofitNetApi 

然后,我们还需要OkHttpClient,通过它可以设置一些属性,例如失败重连和网络拦截器,网络拦截可以设置header


private static final OkHttpClient mOkHttpClient = new OkHttpClient.Builder()
            .retryOnConnectionFailure(true)
            .addNetworkInterceptor(new StethoInterceptor())
            .addInterceptor(chain -> {
                //添加header
                Request original = chain.request();
                Request request = original.newBuilder()
                        .header("X-Token", token)
                        .addHeader("X-Device-ID", deviceID)
                        .addHeader("X-UID", userID + "")
                        .addHeader("X-App-Version", version + "")
                        .addHeader("user-agent", UA)
                        .build();

                return chain.proceed(request);
            })
            .build();

这种设置header的方式是okhttp的方式,通过拦截器设置header;其实,Retrofit也有设置header的方式,但是它是属于传参数的形式,需要每一个网络接口请求的时候进行设置,不利于封装,重用了代码。例如:

@GET("user")
Call<ResponseBody> getUser(@Header("header1") String header)

最后,封装一个通用的RetrofitClient用于调用网络请求接口。

    public static RetrofitNetApi getNetApi() {
        if (RetrofitApi == null) {
            Retrofit retrofit = new Retrofit.Builder()
                    .client(mOkHttpClient)
                    .baseUrl(getUrl())
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
            RetrofitApi = retrofit.create(RetrofitNetApi.class);
        }
        return RetrofitApi;
    }

baseUrl()是你的基础网络请求接口,例如是"www.shadow.com/user",那个"baseUrl"就是"www.shadow.com"。addConverterFactory(GsonConverterFactory.create())是吧json结果并解析成DAO,也可以添加其他的解析方式,但是必须换其他方式的依赖。

2.定义Retrofit网络接口

首先是一个简单的Get请求
网络接口是这样的”www.shadow.com/xxx/session
那我们可以这样

@GET("account/session")
Call<ResponseBody> getSession();

还有很多

例如Get请求 "www.shadow.com/xxxx/book?pageIndex=1&pageSize=20"

你可以这么拼接你的网络请求,使用操作符@Query

@GET("xxxx/book")
Call<ResponseBody> book(@Query("pageIndex") String pageIndex, @Query("pageSize") String pageSize);

还有Get请求 "www.shadow.com/xxxx/bookname" 通过替换bookname来请求接口,
可以使用操作符@Path

@GET("xxxx/{bookname}")
Call<ResponseBody> bookname(@Path("bookname") String bookname);

Post请求 "www.shadow.com/xxxx/booklist" 需要提交参数,可以使用操作符@Field,而且不用忘记加上@FormUrlEncoded.

@FormUrlEncoded
@POST("xxxx/booklist")
Call<ResponseBody> booklist(@Field("booklist") String booklist);

而且@Field不限制请求方式,你用Put也可以,但是不能忘记@FormUrlEncoded

@FormUrlEncoded
@PUT("xxxx/booklist")
Call<ResponseBody> booklist(@Field("booklist") String booklist);

其实Retrofit的请求方式很灵活,几乎能满足你想要的各种姿势。

例如是这样的Get请求
"www.shadow.com/xxxx/bookname/book?pageIndex=1&pageSize=20"

@GET("xxxx/{bookname}/book")
Call<ResponseBody> bankLimit(@Path("bookname") String bookname, @Query("pageIndex") String pageIndex,@Query("pageSize") String pageSize);

或者是这样的Post请求
"www.shadow.com/xxxx/bookname/booklist"


@FormUrlEncoded
@POST("xxxx/{bookname}/booklist")
Call<ResponseBody> bonusAutoInvest(@Path("bookname") int bookname, @Field("booklist") boolean booklist);

就是这么的好玩

封装通用网络库

按照以上说的,我们已经把网络接口定义好了,那现在需要封装通用网络库。
上面的代码,可以发现我的网络接口返回的都是Call<ResponseBody>,而不是Observable<T>

Call<T>是Retrofit的一个Call形式的参数回调,T是任意泛型,这个Call<T>有一个网络发送请求的方法,是同步的。

ResponseBody是okhttp的一个请求体,可以封装json。

这样使用,是因为我不想直接获取已经解析好的bean,而是拿到json,更加的灵活判断网络请求的各种状况。

以下代码是用RxJava封装的网络库


private Observable<String> getResults(Call<ResponseBody> call, int delay) {

        return Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(final Subscriber<? super String> subscriber) {
                try {
                    retrofit2.Response<ResponseBody> response = call.execute();
                    String result = response.body() != null ? response.body().string() : "";
                    String error = response.errorBody() != null ? response.errorBody().string() : "";
                    int code = response.code();
                   
                    if (response.isSuccessful()) {  //返回值在200至300之间表示返回成功
                        //根据某种约定的特殊处理 没有返回值
                        if (!result.startsWith("{") && (!result.startsWith("[")) || code == 204 || result.equals("{}"){ 
                            subscriber.onNext("ok");
                        } else {    //有返回值
                            subscriber.onNext(result);
                        }

                    } else {    //请求失败时的处理
                        if (TextUtils.isEmpty(error)) {    //没有返回标准的报错信息
                            subscriber.onError(new Exception("code:" + code));
                        } else {
                            subscriber.onError(new Exception(error));
                        }
                    }
                } catch (Exception e) {
                            subscriber.onError(e);
                }
            }

        }).delay(delay, TimeUnit.MILLISECONDS);
    }


如代码,我可以吧网络接口Call<ResponseBody>传参进去,执行网络请求,然后根据返回回来的json,不同的情况做不同的处理,最后用subscriber回调正确或者错误的结果。正确的json可以解析成我们需要的bean,错误的json可以根据不同的状况作出不同的错误处理,这样一来比较灵活和解耦,能处理各种不同的网络请求的需求。

最外层的就是普通的Rxjava调用了,这里就不描述了。

最后,这就是我使用的Retrofit 2.0网络库的封装和各种应用场景,给我的感觉就是Retrofit非常的简洁和高效。

最后

这是一个简洁实用的网络封装,记录一下思路。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容