Retrofit2.0+RxJava+RxAndroid——强强联合的网络请求框架

from  :  http://blog.youkuaiyun.com/yehui928186846/article/details/51492571


最近看了很多关于Retrofit和Rxjava的文档介绍。终于在弄清Rxjava后顺利的弄懂了Retrofit。

网上有很多人都介绍了它们的联合使用,但是我看过之后理解不是太好。可能我太笨。 
不过,今天写这篇博客的目的就是想来说说它们之间如何使用以及使用的时候遇到的坑。

这两者的关系并不大,但是联合在一起使用是非常简便的。Rxjava的响应式编程加上Retrofit的注解式请求用起来是非常爽的。 
并且Retrofit内置的是Okhttp,所以这更加的让Retrofit变得强大。

如果在看这篇博客的时候你对java注解、Rxjava还有Okhttp还不够了解,建议先去了解这两个东西。

给出友情链接:

java 注解——使用详解

RxJava——响应式和区域化的优秀框架(java&android)

android http——OkHttp使用详解

相信看到这里,你已经对上面三个知识有了了解。

那么接下来切入正题。 
先来加入依赖库:

<code class="hljs bash has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">    compile <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'io.reactivex:rxjava:1.0.14'</span>
    compile <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'io.reactivex:rxandroid:1.0.1'</span>
    compile <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'com.squareup.retrofit:adapter-rxjava:2.0.0-beta2'</span>
    compile <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'com.squareup.retrofit:retrofit:2.0.0-beta2'</span>
    compile <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'com.squareup.retrofit:converter-gson:2.0.0-beta2'</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>

没错,你需要的库就是这么多。若要联合它们三者使用,就必须这么多。 
我来按顺序介绍。 
1,Rxjava库 
2,RxAndroid库 
3,Retrofit适配Rxjava的库 
4,Retrofit库 
5,Retrofit适配Gson的库(添加了这个库后不用再添加Gson库,因为已经内置)

另外还要有Okhttp依赖库。在android sdk中已经内置。似乎Retrofit中也内置了Okhttp,所以我项目中没有加入okhttp依赖库,但是okhttp依旧可以使用。

这里需要说明一下,第五个依赖库根据你的项目需求来添加。 
一般的项目来说都是使用json数据的。若你的项目是使用xml或者其他的数据格式,那么对应的添加。 
(以下版本号需要与retrofit版本号保持一致,并且以retrofit官网给出的版本号为准。)

<code class="hljs http has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-attribute" style="box-sizing: border-box;">1)Gson</span>: <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">compile 'com.squareup.retrofit2:converter-gson:2.0.1'</span>

<span class="http" style="box-sizing: border-box;"><span class="hljs-attribute" style="box-sizing: border-box;">2)Jackson</span>: <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">compile 'com.squareup.retrofit2:converter-jackson:2.0.1'</span>

<span class="http" style="box-sizing: border-box;"><span class="hljs-attribute" style="box-sizing: border-box;">3)Moshi</span>: <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">compile 'com.squareup.retrofit2:converter-moshi:2.0.1'</span>

<span class="http" style="box-sizing: border-box;"><span class="hljs-attribute" style="box-sizing: border-box;">4)Protobuf</span>: <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">compile 'com.squareup.retrofit2:converter-protobuf:2.0.1'</span>

<span class="http" style="box-sizing: border-box;"><span class="hljs-attribute" style="box-sizing: border-box;">5)Wire</span>: <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">compile 'com.squareup.retrofit2:converter-wire:2.0.1'</span>

<span class="lasso" style="box-sizing: border-box;"><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span>)Simple <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">XML</span>: compile <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'com.squareup.retrofit2:converter-simplexml:2.0.1'</span>

<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7</span>)Scalars (primitives, boxed, <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">and</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span>): compile <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'com.squareup.retrofit2:converter-scalars:2.0.1'</span></span></span></span></span></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li></ul>

好了。依赖库加完以后。我们就开始请求了。

我们先来个测试url

<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> String ip = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"http://gc.ditu.aliyun.com/geocoding?a=上海市&aa=松江区&aaa=车墩镇"</span>;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

这个是阿里云根据地区名获取经纬度接口。 
返回json数据

<code class="hljs json has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">{
    "<span class="hljs-attribute" style="box-sizing: border-box;">lon</span>":<span class="hljs-value" style="box-sizing: border-box;"><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">120.58531</span></span>,
    "<span class="hljs-attribute" style="box-sizing: border-box;">level</span>":<span class="hljs-value" style="box-sizing: border-box;"><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span></span>,
    "<span class="hljs-attribute" style="box-sizing: border-box;">address</span>":<span class="hljs-value" style="box-sizing: border-box;"><span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">""</span></span>,
    "<span class="hljs-attribute" style="box-sizing: border-box;">cityName</span>":<span class="hljs-value" style="box-sizing: border-box;"><span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">""</span></span>,
    "<span class="hljs-attribute" style="box-sizing: border-box;">alevel</span>":<span class="hljs-value" style="box-sizing: border-box;"><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span></span>,
    "<span class="hljs-attribute" style="box-sizing: border-box;">lat</span>":<span class="hljs-value" style="box-sizing: border-box;"><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">31.29888</span>
</span>}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>

我们先来写好实体类AliAddrsBean和IndexRequestBean

<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> AliAddrsBean {
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> lon;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> level;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> String address;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> String cityName;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> alevel;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> lat;
     <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//get/set方法忽略</span>
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> IndexRequestBean {
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> String a;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//一级城市</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> String aa;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//二级城市</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> String aaa;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//三级城市</span>
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//get/set方法忽略</span>
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>

Retrofit的请求管理类RetrofitManage(先写成单例)

<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-title" style="box-sizing: border-box;">RetrofitManage</span>() {
    }

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> RetrofitManage <span class="hljs-title" style="box-sizing: border-box;">getInstance</span>() {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> RetrofitManager.retrofitManage;
    }

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> RetrofitManager {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> final RetrofitManage retrofitManage = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> RetrofitManage();
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li></ul>

定义一个发送网络请求的方法sendRequest()

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">public void sendRequest(String url) {      
        //每一个<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Call</span>实例可以同步(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">call</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.excute</span>())或者异步(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">call</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.enquene</span>(CallBack<?> callBack))的被执行,
        //每一个实例仅仅能够被使用一次,但是可以通过clone()函数创建一个新的可用的实例。
        //默认情况下,Retrofit只能够反序列化Http体为OkHttp的ResponseBody类型
        //并且只能够接受ResponseBody类型的参数作为@body
        Retrofit retrofit = new Retrofit
                <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Builder</span>()
                <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.baseUrl</span>(url)
                <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.addCallAdapterFactory</span>(RxJavaCallAdapterFactory<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.create</span>()) // 使用RxJava作为回调适配器
                <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.addConverterFactory</span>(GsonConverterFactory<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.create</span>()) // 使用Gson作为数据转换器
                <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.build</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li></ul>

Retrofit 实例化 注意事项: 
1,每一个Call实例的用法和okhttp的call几乎一样。 
2,call只能被使用一次,若再次调用会抛出异常。如果需要多次使用请使用clone 
3,默认反序列化OkHttp的ResponseBody类型 
4,默认只能接受ResponseBody类型的参数作为@body 
5,2.0以后,get请求和post的请求的区别在call里面,注解写@get和写@post已经没有区别了 
sendRequest()方法中已经写的很清楚了,不再多说。

承载一切请求的接口ApiService

这个类我要分开写,因为内容实在太多。

规则:每一个函数都必须有提供请求方式和相对URL的Http注解

Retrofit提供了5种内置的注解:GET、POST、PUT、DELETE和HEAD

注解中指定的资源是相对的URL 
注解中指定的资源是相对的URL 
注解中指定的资源是相对的URL

为啥说三遍,不解释。 
这是第一个细节也是第一个门槛。 
注解里到底写的是什么?

我们先来看看一个简单的、迷茫的get请求。

<code class="hljs css has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-at_rule" style="box-sizing: border-box;">@<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">GET("search/repositories")</span>
Call<RetrofitBean> <span class="hljs-function" style="box-sizing: border-box; color: rgb(0, 102, 102);">queryRetrofitByGetCall(
                                      @<span class="hljs-function" style="box-sizing: border-box;">Query(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"name"</span>)</span>String name,
                                      @<span class="hljs-function" style="box-sizing: border-box;">Query(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"pwd"</span>)</span>String pwd)</span></span>;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>

url呢? 
注解里写的啥? 
query又是啥? 
怎么调用? 
怎么返回? 
这是我在网上看到最多的示例。 
我就搞不懂了,给一个初学者写这么一个东西谁看得懂?

所以,我来一步一步的解释清楚,写一个易懂的例子。

先来回顾一下我们的url:http://gc.ditu.aliyun.com/geocoding?a=上海市&aa=松江区&aaa=车墩镇

参照这个url我们来写一个get请求:

<code class="hljs css has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-at_rule" style="box-sizing: border-box;">@<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">GET("http://gc.ditu.aliyun.com/geocoding?a=上海市&aa=松江区&aaa=车墩镇")</span>
    Call<AliAddrsBean> <span class="hljs-function" style="box-sizing: border-box; color: rgb(0, 102, 102);">getIndexContent()</span></span>;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

这么看就明白了吧,注解中就是一个url而已。 
看看怎么调用的

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">Retrofit retrofit = new Retrofit
                <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Builder</span>()
                <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.baseUrl</span>(url)         <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.addCallAdapterFactory</span>(RxJavaCallAdapterFactory<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.create</span>())              <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.addConverterFactory</span>(GsonConverterFactory<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.create</span>()) 
                <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.build</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        ApiService service = retrofit<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.create</span>(ApiService<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.class</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Call</span><AliAddrsBean> requestInde = service<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getIndexContent</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        requestInde<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.execute</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;//同步请求,和okhttp的使用方法一样</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>

这就是最简单粗暴的调用方法。这里需要注意的是,我们还需要传入一个实体类作为返回数据的解析依据。

这里我们就是传入的AliAddrsBean。Retrofit已经帮我们把数据解析好了。

可以看出来我们在外面调用了.baseUrl(url) ,为什么在注解中还需要写url呢? 
这就关系到很多的细节和坑了。

现在我们假定我们的url是这样的:http://gc.ditu.aliyun.com/geocoding?

如果我们在注解里面这么写: 
(以下有坑)

<code class="hljs css has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-at_rule" style="box-sizing: border-box;">@<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">GET("a=上海市&aa=松江区&aaa=车墩镇")</span>
    Call<AliAddrsBean> <span class="hljs-function" style="box-sizing: border-box; color: rgb(0, 102, 102);">getIndexContentOne()</span></span>;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

看似是对的,其实在我做demo的时候用okhttp请求成功但是用retrofit请求一直失败。 
究其原因就是:注解中必须要有一部分的url地址,不能光是请求体。

所以,修改代码: 
请求url:http://gc.ditu.aliyun.com/

以下是正解:

<code class="hljs css has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-at_rule" style="box-sizing: border-box;">@<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">GET("geocoding?a=上海市&aa=松江区&aaa=车墩镇")</span>
    Call<AliAddrsBean> <span class="hljs-function" style="box-sizing: border-box; color: rgb(0, 102, 102);">getIndexContentOne()</span></span>;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

这么一写,果然请求正常了。

另外还有一个坑,Retrofit建议url以/结束,注解不要以/开始

我们将get请求汇入接口ApiService中:

基本get请求

<code class="hljs scss has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//实际上在get的开始已经有一个rul存在了</span>
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//例如,我们的url是“http://gc.ditu.aliyun.com/”</span>
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//那么get注解前就已经存在了这个url,并且使用{}替换符得到的最终url是:</span>
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// http://gc.ditu.aliyun.com/geocoding?a=苏州市</span>
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//参数不能为null,且不能只有url的参数,还应该包括地址的字段;正确:geocoding?a=苏州市;错误:a=苏州市</span>
    <span class="hljs-at_rule" style="box-sizing: border-box;">@<span class="hljs-function" style="box-sizing: border-box;">GET(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"geocoding?a=苏州市"</span>)</span>
   <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"> Call</span><AliAddrsBean><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"> getIndexContentOne</span>();</span>

    <span class="hljs-at_rule" style="box-sizing: border-box;">@<span class="hljs-function" style="box-sizing: border-box;">GET(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"http://gc.ditu.aliyun.com/geocoding?a=上海市&aa=松江区&aaa=车墩镇"</span>)</span>
   <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"> Call</span><AliAddrsBean><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"> getIndexContent</span>();</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li></ul>

{ }取代块和@Path

<code class="hljs mathematica has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">    //这里需要注意的是,<span class="hljs-list" style="box-sizing: border-box;">{}</span>作为取代块一定不能取代参数
    //它会报异常:<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">URL</span> query string <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"a={city}"</span> must not have replace block. <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">For</span> dynamic query parameters use @Query.
    //翻译:<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">URL</span>查询字符串“= <span class="hljs-list" style="box-sizing: border-box;">{城市}</span>”必须没有取代块。动态查询参数使用@Query。
    //所以,<span class="hljs-list" style="box-sizing: border-box;">{}</span>取代块只能替换url而不能替换参数参数应该用@query
    @GET(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"{parameters}?a=苏州市"</span>)
    Call<AliAddrsBean> getIndexContentOne(
            @<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Path</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"parameters"</span>) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">String</span> parameters);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>

所以,取代块只能取代url,不能取代参数,且@path的作用就是专职于取代块 
调用的时候把参数传进来

<code class="hljs sql has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-operator" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Call</span><AliAddrsBean> requestInde = service.getIndexContentOne(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"geocoding"</span>);</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

@Query 键值对传参

看到那么多参数请求,肯定有简单的方法,单个参数添加

<code class="hljs scss has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//看到那么多参数请求,肯定有简单的方法,单个参数添加</span>
    <span class="hljs-at_rule" style="box-sizing: border-box;">@<span class="hljs-function" style="box-sizing: border-box;">POST(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"geocoding?"</span>)</span>
   <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"> Call</span><AliAddrsBean><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"> getIndexContentTow</span>(
            @<span class="hljs-function" style="box-sizing: border-box;">Query(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"a"</span>)</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"> String</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"> key1</span>,
            @<span class="hljs-function" style="box-sizing: border-box;">Query(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"aa"</span>)</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"> String</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"> key2</span>,
            @<span class="hljs-function" style="box-sizing: border-box;">Query(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"aaa"</span>)</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"> String</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"> key3</span>
    );</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>

调用:

<code class="hljs sql has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-operator" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Call</span><AliAddrsBean> requestInde = service.getIndexContentTow(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"苏州市"</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"苏州市"</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"苏州市"</span>);</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

@query的作用就相当于拼接字符串:a=上海市&aa=松江区&aaa=车墩镇

@QueryMap 参数集合

有时候我们参数很多,一个一个的用@query去传肯定不方便。

<code class="hljs javascript has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//看到那么多参数请求,肯定有简单的方法,多个参数添加使用map</span>
    @GET(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"geocoding?"</span>)
    Call<AliAddrsBean> getIndexContentThree(
            @QueryMap Map<<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span>, <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">Object</span>> options
    );</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>

调用:

<code class="hljs vhdl has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Map</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">map</span> = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> HashMap();
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">map</span>.put(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"a"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"上海市"</span>);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">map</span>.put(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"aa"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"黄浦区"</span>);
Call<AliAddrsBean> requestInde = service.getIndexContentThree(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">map</span>);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>

@Body 请求体

我们可以把参数封装成一个实体类,然后传过去。这么做比map传参更加方便。

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//可以通过@Body注解指定一个对象作为Http请求的请求体</span>
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//类似于一二三级城市的参数都放在的请求体indexRequestBean里面</span>
    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@POST</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"geocoding?"</span>)
    Call<AliAddrsBean> getIndexContentFour(
            <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Body</span> IndexRequestBean indexRequestBean);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>

调用

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">IndexRequestBean indexRequestBean = new IndexRequestBean()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
indexRequestBean<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setA</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"上海市"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
indexRequestBean<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setAa</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"松江区"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
indexRequestBean<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setAaa</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"车墩镇"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Call</span><AliAddrsBean> requestInde = service<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getIndexContentFour</span>(indexRequestBean)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>

这种做法得到的结果一样,但是方便了许多。

@FormUrlEncoded 和@Field 发送表单数据

@FormUrlEncoded注解的时候,将会发送form-encoded数据

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//函数也可以声明为发送form-encoded(表单形式)和multipart(多部分)数据。</span>
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//当函数有@FormUrlEncoded注解的时候,将会发送form-encoded数据,</span>
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//每个键-值对都要被含有名字的@Field注解和提供值的对象所标注(这他妈是绕口令吗?)</span>
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//每个键值对的写法都是用注解@field标识的,表单形式的数据</span>
    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@FormUrlEncoded</span>
    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@POST</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"geocoding?"</span>)
    Call<AliAddrsBean> getIndexContentFive(
            <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Field</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"a"</span>) String city,
            <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Field</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"aa"</span>) String citys,
            <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Field</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"aaa"</span>) String cityss
    );</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li></ul>

调用:

<code class="hljs sql has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-operator" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Call</span><AliAddrsBean> requestInde = service.getIndexContentFive(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"苏州市"</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"苏州市"</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"苏州市"</span>);</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

@Multipart和@Part 发送字节流数据

我们有时候要在发送请求前规定数据的编码格式,那么我们就可以用这个注解来解决。

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//当函数有@Multipart注解的时候,将会发送multipart数据,</span>
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Parts都使用@Part注解进行声明</span>
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//Multipart parts要使用Retrofit的众多转换器之一或者实现RequestBody来处理自己的序列化。</span>
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//这个可以用于传文件,可以改变传值的编码,默认utf_8</span>
    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Multipart</span>
    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@POST</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"geocoding?"</span>)
    Call<AliAddrsBean> getIndexContentSix(
            <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Part</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"a"</span>) RequestBody city,
            <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Part</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"aa"</span>) RequestBody citya,
            <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Part</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"aaa"</span>) RequestBody cityaa);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li></ul>

可能这样看不太懂,那么我们就看看如何调用的就懂了

<code class="hljs sql has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">RequestBody requestBody1 = RequestBody.<span class="hljs-operator" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">create</span>(MediaType.parse(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"UTF-8"</span>), <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"苏州市"</span>);</span>//如果传值为null,则默认utf——8
//        RequestBody requestBody2 = RequestBody.<span class="hljs-operator" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">create</span>(MediaType.parse(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"UTF-8"</span>), <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"苏州市"</span>);</span>
//        RequestBody requestBody3 = RequestBody.<span class="hljs-operator" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">create</span>(MediaType.parse(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"UTF-8"</span>), <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"苏州市"</span>);</span>
//        <span class="hljs-operator" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Call</span><AliAddrsBean> requestInde = service.getIndexContentSix(requestBody1,requestBody2,requestBody3);</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>

当然,既然是requestbody类型,我们就可以用它来穿文件了。

<code class="hljs livecodeserver has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">RequestBody requestBody1 = RequestBody.<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">create</span>(MediaType.parse(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"UTF-8"</span>), <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">new</span> File(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"aaa"</span>))<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;//如果传值为null,则默认utf——8</span>
</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

@Headers给函数设置header

对于给一个请求设置header我在日志中看到打印了header的内容。 
如果我们每次都要给服务器一些固定参数,,例如版本号,请求接口版本,key等。我们就可以用它来设置在http请求的头里。

<code class="hljs scss has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//可以使用@Headers注解给函数设置静态的header</span>
    <span class="hljs-at_rule" style="box-sizing: border-box;">@<span class="hljs-function" style="box-sizing: border-box;">Headers({<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"key:web_service_key"</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"web_vsersion:1.01"</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"app_version:1.02"</span>})</span>
    @<span class="hljs-function" style="box-sizing: border-box;">GET(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"geocoding?"</span>)</span>
   <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"> Call</span><AliAddrsBean><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"> getIndexContentSeven</span>(
            @<span class="hljs-function" style="box-sizing: border-box;">Query(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"a"</span>)</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"> String</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"> city</span>
    );</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>

调用和get请求没有区别。是不是很方便?

@Header 单个参数的header

我感觉这个没什么卵用。。。 
不过还是贴出来使用方法

<code class="hljs scss has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//可以使用@Header注解动态的更新一个请求的header。必须给@Header提供相应的参数,</span>
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果参数的值为空header将会被忽略,否则就调用参数值的toString()方法并使用返回结果</span>
    <span class="hljs-at_rule" style="box-sizing: border-box;">@<span class="hljs-function" style="box-sizing: border-box;">GET(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"geocoding?"</span>)</span>
   <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"> Call</span><AliAddrsBean><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"> getIndexContentNine</span>(
            @<span class="hljs-function" style="box-sizing: border-box;">Header(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"a"</span>)</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"> String</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"> city</span>
    );</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>

适配Rxjava

这么多的Retrofit都是返回的call,我们应该如何适配Rxjava呢? 
Retrofit默认是可以适配Rxjava的。 
所以我们要做的就是:

<code class="hljs scss has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//我们适配Rxjava的时候,只需要将返回结果的call变成Rxjava的被订阅者Observable即可</span>
    <span class="hljs-at_rule" style="box-sizing: border-box;">@<span class="hljs-function" style="box-sizing: border-box;">GET(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"geocoding?"</span>)</span>
   <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"> Observable</span><AliAddrsBean><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"> getIndexContentEleven</span>(
            @<span class="hljs-function" style="box-sizing: border-box;">Query(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"a"</span>)</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"> String</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"> city</span>);</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>

调用:

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">Observable<AliAddrsBean> requestInde = service<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getIndexContentEleven</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"苏州市"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

我们得到了带有网络请求数据的Observable对象后我们就可以依照Rxjava来做一系列的响应式编程了。

这里还有一个坑,先看我们如何处理数据 
(以下有坑)

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> requestInde.subscribe(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Action1<AliAddrsBean>() {
                    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">call</span>(AliAddrsBean aliAddrsBean) {
                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//这里我只返回了成功的结果</span>

                    }
                });</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>

我们直接给观察者或者叫订阅者发送消息“嘿!网络请求的数据回来了!”

这样做看似没问题,但是在我实际运行中却报错了。 
异常表示数据处理需要在非ui线程。

那么就很了然了。我们得到requestInde的对象后要在非ui线程中操作。

以下代码已经填坑

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">Observable<AliAddrsBean> requestInde = service.getIndexContentEleven(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"苏州市"</span>);
        requestInde.subscribeOn(Schedulers.newThread())<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//这里需要注意的是,网络请求在非ui线程。如果返回结果是依赖于Rxjava的,则需要变换线程</span>
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Action1<AliAddrsBean>() {
                    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">call</span>(AliAddrsBean aliAddrsBean) {
                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//这里我只返回了成功的结果</span>

                    }
                });</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li></ul>

我们要变换线程,处理数据的时候开一个新线程。返回结果就应该在主线程了。这里写android的ui线程就是用到的Rxandroid中的方法。

Observable.zip打包多个网络请求

有时候我们需要边加载数据边下载某个图片或者音乐甚至是各种文件。那么这个时候我们就要把多个网络请求打包起来一起发出去了。

那么这个时候我们就要借助Observable.zip这个操作符了。

先来看如何实现的

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">Observable.zip(
                service.getIndexContentEleven(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"苏州市"</span>),<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//第一个Observable对象</span>
                service.getIndexContentEleven(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"上海市"</span>),<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//第二个Observable对象</span>
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Func2<AliAddrsBean, AliAddrsBean, String>() {<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//function1中传入的是《1,第一个Observable对象;2,第二个Observable对象;3,返回类型》</span>
                    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> String <span class="hljs-title" style="box-sizing: border-box;">call</span>(AliAddrsBean o, AliAddrsBean o2) {
                        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> o.getLat() + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">":"</span> + o2.getLat();
                    }
                })
                .subscribeOn(Schedulers.newThread())<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//这里需要注意的是,网络请求在非ui线程。如果返回结果是依赖于Rxjava的,则需要变换线程</span>
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Subscriber<String>() {
                    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onCompleted</span>() {

                    }

                    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onError</span>(Throwable e) {
                        Log.i(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"test"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"retrofit error "</span> + e.getMessage());
                    }

                    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onNext</span>(String s) {<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//传入的是function1中返回的对象</span>
                        Log.i(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"test"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"retrofit结果1"</span> + s);
                    }
                });</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li></ul>

我们看zip这个操作符的源码可以得知,它能够封装两个被订阅者(Observable)对象。 
并且默认还需要实现一个得到这两个Observable对象中的数据后的二次处理方法(Func2),把这两个对象的结果处理成一个然后发送给观察者(subscribe)。

一开始,并不知道哪个参数对应哪个,看了源码后才搞清楚。方法中我在注释中已经写的很清楚了。

这样我们就把两个网路请求同时进行,然后返回的结果处理成一个拿出来。达到了打包多个网络请求的目的。

添加okhttp委托

因为Retrofit内置okhttp,所以我们也可以为它设置一个委托okhttp对象。 
具体委托方式:

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">Retrofit retrofit = new Retrofit
                <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Builder</span>()
                <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.baseUrl</span>(url)
                <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.client</span>(client)//添加一个okhttp的委托
                <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.addCallAdapterFactory</span>(RxJavaCallAdapterFactory<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.create</span>())  
                <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.addConverterFactory</span>(GsonConverterFactory<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.create</span>()) 
                <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.build</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>

那么这个委托我们能做什么呢? 
这里我写了一个okhttp的拦截器

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">//使用OkHttp拦截器可以指定需要的header给每一个Http请求
        OkHttpClient client = new OkHttpClient()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        //网络拦截器
        client<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.networkInterceptors</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.add</span>(new Interceptor() {
            @Override
            public <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">com</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.squareup</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.okhttp</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Response</span> intercept(Chain chain) throws IOException {

                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">com</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.squareup</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.okhttp</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Response</span> response = chain<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.proceed</span>(chain<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.request</span>())<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

                return response<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
            }
        })<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li></ul>

我们可以做一个okhttp的拦截器,可以打印日志,可以clone 。反正发挥自己的想象,为正在请求的事件做一些额外的事情。

总结

写到这里,这个强强联合的框架已经写完了。 
其实我们可以感觉到,这个框架主要是Retrofit2.0+RxJava+RxAndroid+OkHttp

其中RxAndroid的目的可能就是在android中使用的时候让网络请求回到主线程。

而Retrofit2.0+RxJava+OkHttp则充分的让这个网络请求框架变得如此之简单、之响应式、之模块化。

我们用注解去发送请求,简单、简洁;用Rxjava来让代码块状化,逻辑更清晰;网络请求有okhttp作为强大的后台可以很好的完成各种请求。

其中还有很多没有讲到的,比如Rxjava的RxBus和RxBinding方面。okhttp的更多操作。

因为Retrofit和okhttp一样,不支持下载进度的回调。所以之类附上另一位同行的博客来解决这个问题,顺便自己也学习学习。 
解决Retrofit文件下载进度显示问题

0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值