Retrofit2.0起步篇

retrofit 英文名字是改裝的意思岸售,也就是說(shuō)他是對(duì)網(wǎng)絡(luò)請(qǐng)求的一種改裝旗吁,他不負(fù)責(zé)進(jìn)行網(wǎng)絡(luò)請(qǐng)求痊臭,他是對(duì)請(qǐng)求方式的一種封裝哮肚。真正進(jìn)行網(wǎng)絡(luò)請(qǐng)求的是okhttp。
博客園地址
以下所有內(nèi)容在Android Studio已經(jīng)導(dǎo)入retrofit為基礎(chǔ)广匙。導(dǎo)入方式如下:

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

利用Retrofit進(jìn)行簡(jiǎn)單的GET請(qǐng)求

retrofit在構(gòu)建請(qǐng)求方式之前允趟,需要構(gòu)建一個(gè)接口方法,通過(guò)這個(gè)接口方法的返回值鸦致,來(lái)進(jìn)行網(wǎng)絡(luò)請(qǐng)求潮剪。
下面,來(lái)通過(guò)一些簡(jiǎn)單的例子了解GET請(qǐng)求分唾。

實(shí)驗(yàn)一:對(duì)一個(gè)簡(jiǎn)單的html頁(yè)面進(jìn)行GET請(qǐng)求

我們要獲取百度頁(yè)面的HTML抗碰。首先構(gòu)建如下接口:

public interface HtmlService {
    @GET("/")
    Call<String> getHtml();
}

注意,GET注解中的參數(shù)鳍寂,和方法中的參數(shù)至少要加一個(gè)改含,否則會(huì)報(bào)錯(cuò)。由于迄汛,我們只需要請(qǐng)求www.baidu.com,所以get這里不需要加參數(shù)捍壤,就是/
然后,我們通過(guò)如下步驟鞍爱,來(lái)進(jìn)行網(wǎng)絡(luò)請(qǐng)求鹃觉。
在我們需要進(jìn)行網(wǎng)絡(luò)請(qǐng)求的類中,通過(guò)以下的步驟睹逃,進(jìn)行網(wǎng)絡(luò)請(qǐng)求:

  1. 構(gòu)建retrofit對(duì)象盗扇。
  2. 動(dòng)態(tài)代理生成接口的對(duì)象祷肯。
  3. 通過(guò)接口的方法,得到要請(qǐng)求的API的調(diào)用疗隶。
  4. 通過(guò)同步/異步的方式佑笋,得到response。
  5. 根據(jù)需要斑鼻,處理response蒋纬。

第一步

Retrofit retrofit = new Retrofit.Builder().          addConverterFactory(ScalarsConverterFactory.create()).
                baseUrl("https://www.baidu.com").
                build();

通過(guò)以上代碼,可以簡(jiǎn)單的構(gòu)建一個(gè)retrofit對(duì)象坚弱,addConverterFactory是對(duì)response進(jìn)行解析蜀备,里面添加的參數(shù)是表示對(duì)response用String解析,然后添加一個(gè)基礎(chǔ)的URL荒叶,后續(xù)的參數(shù)則是通過(guò)上面我們定制的接口來(lái)添加碾阁,最后構(gòu)建一個(gè)完整的URL。
第二步

HtmlService htmlService = retrofit.create(HtmlService.class);

通過(guò)動(dòng)態(tài)代理些楣,生成一個(gè)接口的對(duì)象脂凶。

第三步

Call<String> call = htmlService.getHtml();

通過(guò)接口的方法得到調(diào)用的對(duì)象。

第四步與第五步
異步方法得到response:

call.enqueue(new Callback<String>() {
            @Override
            public void onResponse(Call<String> call, Response<String> response) {
                showText.append(response.body());
            }

            @Override
            public void onFailure(Call<String> call, Throwable t) {
                Toast.makeText(MainActivity.this,t.getMessage(),Toast.LENGTH_SHORT).show();
            }
        });

得到的response愁茁,通過(guò)response.body()得到響應(yīng)報(bào)文的body部分艰猬。
同步方法得到response:

new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    final String str = call.execute().body();
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            showText.append(str);
                        }
                    });
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();

實(shí)驗(yàn)二:對(duì)一個(gè)返回JSON格式的API進(jìn)行GET請(qǐng)求

通過(guò)GET請(qǐng)求GankIO的api得到Json:
首先,我們也是通過(guò)接口埋市,構(gòu)建一個(gè)接口方法:

@GET("content/{number}/{page}")
Call<HistoryBean> getHistoryData(@Path("number") String number,@Path("page") String page);

這里,方法里面?zhèn)魅氲膮?shù)會(huì)放到@GET的注解里面命贴。
然后道宅,重新構(gòu)建一個(gè)retrofit對(duì)象:

Retrofit retrofit = new Retrofit.Builder().
              addConverterFactory(GsonConverterFactory.create()).
                baseUrl("http://gank.io/api/history/").
                build();

這里面添加的解析器是GsonConverterFactory,表示對(duì)response中body提供對(duì)象解析胸蛛。然后的方法和上面類似:

 HtmlService htmlService = retrofit.create(HtmlService.class);
        call = htmlService.getHistoryData("2", "1");
call.enqueue(new Callback<HistoryBean>() {
            @Override
            public void onResponse(Call<HistoryBean> call, Response<HistoryBean> response) {
                HistoryBean hb = response.body();
                if(hb == null) return;
                showText.append(hb.isError() + "");
                for(HistoryBean.ResultsBean rb : hb.getResults()){
                    showText.append(rb.getTitle() + "/n");
                }
            }

            @Override
            public void onFailure(Call<HistoryBean> call, Throwable t) {

            }
        });

上面的方法是異步得到的污茵,同步的方法和上面類似,就不多說(shuō)了葬项。

實(shí)驗(yàn)三:添加一個(gè)請(qǐng)求參數(shù)構(gòu)建GET請(qǐng)求

上面的GET方法是沒(méi)有查詢參數(shù)的泞当,下面對(duì)一個(gè)有查詢參數(shù)的api,進(jìn)行GET請(qǐng)求,這里我們利用豆瓣的搜索圖書(shū)的API
這個(gè)API接受4個(gè)搜索參數(shù)民珍,具體如下:

參數(shù) 意義 備注
q 查詢關(guān)鍵字 q與tag必傳其一
tag 查詢的tag q與tag必傳其一
start 取結(jié)果的offset 默認(rèn)為0
count 取結(jié)果的條數(shù) 默認(rèn)為20

首先襟士,我們也是構(gòu)建一個(gè)請(qǐng)求接口的方法:

@GET("book/search")
Call<BookBean> queryBookInfo(@Query("q") String name);

在這里面,我們用到了一個(gè)新的注解參數(shù)@Query 這個(gè)參數(shù)表示請(qǐng)求參數(shù)會(huì)以鍵值對(duì)的形式拼接在URL后面嚷量。
這樣的方式陋桂,有一種局限性,因?yàn)橐诿總€(gè)GET接口方法里面寫(xiě)入鍵值對(duì)信息蝶溶,如果嗜历,有些鍵值對(duì)信息是每個(gè)GET方法都需要的,我們就會(huì)通過(guò)一個(gè)攔截器的形式,統(tǒng)一在請(qǐng)求的時(shí)候加上梨州。步驟如下:

  1. 自定義一個(gè)攔截器實(shí)現(xiàn)Interceptor痕囱。
  2. 創(chuàng)建retrofit的客戶端(上面的代碼都是默認(rèn)的客戶端),加上這個(gè)攔截器暴匠。

第一步

public class CustomInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        HttpUrl httpUrl = request.url().newBuilder()
                .addQueryParameter("token", "tokenValue")
                .build();
        request = request.newBuilder().url(httpUrl).build();
        return chain.proceed(request);
    }
}

第二步

OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder().
                addInterceptor(new CustomInterceptor()).
                connectTimeout(1000, TimeUnit.MILLISECONDS);
        
Retrofit retrofit = new Retrofit.Builder().
                client(httpClientBuilder.build()).
                addConverterFactory(GsonConverterFactory.create()).
                baseUrl("https://api.douban.com/v2/").
                build();
HtmlService htmlService = retrofit.create(HtmlService.class);
call = htmlService.queryBookInfo("第一行代碼");

后續(xù)的異步請(qǐng)求基本一致鞍恢,就不細(xì)說(shuō)了。

實(shí)驗(yàn)四:添加多種請(qǐng)求參數(shù)構(gòu)建GET請(qǐng)求

實(shí)驗(yàn)三的部分巷查,講了對(duì)一個(gè)查詢參數(shù)和一個(gè)共有的查詢參數(shù)的GET請(qǐng)求構(gòu)建方法有序,下面多個(gè)查詢參數(shù)的GET請(qǐng)求,看看是否有簡(jiǎn)單的方式岛请,因?yàn)椴幌朐谝粋€(gè)方法里旭寿,傳入4個(gè)以上的參數(shù)。
請(qǐng)求的API還是上邊的豆瓣的搜索API崇败,他正好有4個(gè)請(qǐng)求參數(shù)
下面盅称,看如下構(gòu)建方式:

@GET("book/search")
Call<BookBean> queryBookInfo(@QueryMap Map<String,String> options);

然后,將請(qǐng)求參數(shù)通過(guò)鍵值對(duì)的形式保存到Map里:

 Map<String,String> options = new HashMap<>();
 options.put("q","第一行代碼");
 options.put("start","0");
 options.put("count","1");
 call = htmlService.queryBookInfo(options);

在上面的情況下后室,有多種鍵值對(duì)缩膝,每一種key對(duì)應(yīng)的value都是唯一的,retrofit也支持相同的key岸霹,卻有多種value的形式疾层。方式如下:

@GET("book/search")
Call<BookBean> queryBookInfo(@Query("key") List<String> value);

然后,將value的集合傳入方法中贡避,后續(xù)的步驟不變痛黎,就不多數(shù)。

利用Retrofit進(jìn)行簡(jiǎn)單的POST請(qǐng)求

利用retorfit進(jìn)行post請(qǐng)求與進(jìn)行g(shù)et請(qǐng)求沒(méi)有太多的區(qū)別刮吧。主要的區(qū)別就在構(gòu)建接口方法上面湖饱,有一些不同,下面通過(guò)一些實(shí)驗(yàn)來(lái)看一下具體的區(qū)別杀捻。

實(shí)驗(yàn)一:將少數(shù)參數(shù)放到請(qǐng)求體中進(jìn)行POST請(qǐng)求

下面的POST方法API是我自己寫(xiě)的后臺(tái)來(lái)接受簡(jiǎn)單的POST井厌,就不放出來(lái)了。
首先致讥,也是構(gòu)建一個(gè)接口方法:

@FormUrlEncoded
@POST("login")
Call<String> doLogin(@Field("name")String name,@Field("password") String password);

第一個(gè)注解仅仆,表示自動(dòng)將請(qǐng)求參數(shù)的類型調(diào)整為application/x-www-form-urlencoded ,如果方法參數(shù)的注解用了@Field 就一定要用@FormUrlEncoded拄踪。POST注解里面依舊放的是API蝇恶,方法參數(shù)通過(guò)@Field將請(qǐng)求參數(shù)放置在請(qǐng)求體中。
后續(xù)創(chuàng)建retrofit對(duì)象,創(chuàng)建call對(duì)象,發(fā)起請(qǐng)求,都是和GET方法一樣匈织,就不多說(shuō)了贿衍。

實(shí)驗(yàn)二:將多個(gè)參數(shù)放到請(qǐng)求體中進(jìn)行POST請(qǐng)求

這個(gè)只不過(guò)構(gòu)建接口方法的時(shí)候授舟,有所區(qū)別,其他步驟和多種參數(shù)進(jìn)行GET請(qǐng)求一樣贸辈。

@FormUrlEncoded
@POST("login")
Call<String> doLogin(@FieldMap Map<String,String> fields);

將多個(gè)請(qǐng)求參數(shù)保存到Map中释树,傳入方法中,沒(méi)什么好說(shuō)的擎淤。

實(shí)驗(yàn)三:利用POST進(jìn)行文件上傳

同樣構(gòu)建一個(gè)接口方法:

@Multipart
@POST("upload")
Call<ResponseBody> uploadFile(@Part("description") RequestBody description,
@Part MultipartBody.Part file);

這里的POST修飾注解就換成了@Multipart ,在方法參數(shù)里面奢啥,通過(guò)@Part注解來(lái)修飾參數(shù)。
我們說(shuō)一下具體怎么構(gòu)建這些方法的參數(shù)嘴拢。
首先桩盲,構(gòu)建一個(gè)RequestBody對(duì)象的description,構(gòu)建方式如下:

RequestBody description = RequestBody.create(MediaType.parse("multipart/form-data"), "這是一個(gè)文件");

然后席吴,構(gòu)建一個(gè)MultipartBody.Part對(duì)象的file赌结,不過(guò)在構(gòu)建之前,先要?jiǎng)?chuàng)建一個(gè)RequestBody對(duì)象孝冒,通過(guò)這個(gè)對(duì)象才能創(chuàng)建一個(gè)MultipartBody.Part對(duì)象柬姚。代碼如下:

RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"),file);
MultipartBody.Part body = MultipartBody.Part.createFormData("file",file.getName(),requestBody);

然后和其他方法一樣,利用這些對(duì)象庄涡,生成call量承,然后進(jìn)行網(wǎng)絡(luò)請(qǐng)求。

 call = service.uploadFile(description,body);

當(dāng)然穴店,retrofit支持多種上傳圖片的方式宴合,其構(gòu)建方式如下:

// 上傳多個(gè)文件
    @Multipart
    @POST("upload")
    Call<ResponseBody> uploadMultipleFiles(
            @Part("description") RequestBody description,
            @Part MultipartBody.Part file1,
            @Part MultipartBody.Part file2);

以上這些實(shí)驗(yàn)就是利用Retrofit實(shí)現(xiàn)簡(jiǎn)單POST 請(qǐng)求。

添加HEADER

我們?cè)谶M(jìn)行復(fù)雜的網(wǎng)絡(luò)請(qǐng)求的時(shí)候迹鹅,通常要對(duì)請(qǐng)求添加頭部,retrofit提供了多種添加方式贞言,可以分為如下兩種:

  1. 靜態(tài)添加頭部
  2. 動(dòng)態(tài)添加頭部

靜態(tài)添加頭部

靜態(tài)添加頭部斜棚,則每次請(qǐng)求的時(shí)候,頭部的信息都是固定的该窗,不可以更改的弟蚀。添加靜態(tài)頭部的方式也有多種,方法如下:

  1. 在接口中添加酗失。
  2. 通過(guò)攔截器添加义钉。

下面,我們分別說(shuō)一說(shuō)每一種规肴。
在接口中添加
還是以上文寫(xiě)到的接口為例捶闸,添加Cache-Control,User-Agent請(qǐng)求頭部夜畴。

@Headers({
            "Cache-Control: max-age=640000",
            "User-Agent: app-name"
    })

通過(guò)攔截器添加
和上面統(tǒng)一處理GET參數(shù)的定制器一樣,同樣實(shí)現(xiàn)Interceptor,代碼如下:

public class RequestInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request original = chain.request();
        Request request = original.newBuilder()
                .header("User-Agent", "app-name")
                .header("Cache-Control", "max-age=640000")
                .method(original.method(), original.body())
                .build();
        return chain.proceed(request);
    }
}

然后删壮,在創(chuàng)建okHttp的客戶端時(shí),把攔截器加進(jìn)去贪绘,創(chuàng)建retrofit對(duì)象時(shí),指定該客戶端即可央碟。

  OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder().
                addInterceptor(new CustomInterceptor()).
                addInterceptor(new RequestInterceptor()).
                connectTimeout(1000, TimeUnit.MILLISECONDS);

動(dòng)態(tài)添加頭部

動(dòng)態(tài)添加的好處税灌,就在于不同的請(qǐng)求會(huì)有不同的請(qǐng)求頭部,那么可想而知亿虽,其添加的部分就是在接口方法里面菱涤。

@GET("{number}/{page}")
Call<HistoryBean> getHistoryData(@Header("Content-Range") String contentRange ,@Path("number") String number, @Path("page") String page);

后續(xù)的使用都是一樣的,沒(méi)什么好說(shuō)的洛勉。

設(shè)置網(wǎng)絡(luò)請(qǐng)求日志

retrofit提供了對(duì)網(wǎng)絡(luò)請(qǐng)求的過(guò)程進(jìn)行打印的日志的插件粘秆,需要單獨(dú)的導(dǎo)入,其方式如下:

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

通過(guò)上面的導(dǎo)入代碼坯认,可以看出這個(gè)日志插件是okHttp特有的翻擒,這也可以證明,retrofit只是封裝了請(qǐng)求的方式牛哺,真正請(qǐng)求的還是通過(guò)okHttp陋气。那么我們也可以猜出,其設(shè)置的方式必然也是通過(guò)攔截器引润,放進(jìn)okHttp的客戶端里面巩趁。具體的代碼如下:

HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder().
                addInterceptor(new CustomInterceptor()).
                addInterceptor(new RequestInterceptor()).
                addInterceptor(httpLoggingInterceptor).
                connectTimeout(1000, TimeUnit.MILLISECONDS);

注意上面的代碼,在設(shè)置請(qǐng)求級(jí)別上面設(shè)置為body淳附,下面說(shuō)一下具體的級(jí)別以及其內(nèi)涵:

  1. NONE : 沒(méi)有任何日志信息议慰。
  2. Basic : 打印請(qǐng)求類型,URL奴曙,請(qǐng)求體大小别凹,返回值狀態(tài)以及返回值的大小。
  3. Headers : 打印返回請(qǐng)求和返回值的頭部信息洽糟,請(qǐng)求類型炉菲,URL以及返回值狀態(tài)碼
  4. Body : 打印請(qǐng)求和返回值的頭部和body信息。

總結(jié)

上面就是簡(jiǎn)單的retrofit的使用坤溃,關(guān)于利用retrofit結(jié)合其他部分如Rx拍霜,okHttp等等,或者利用retrofit實(shí)現(xiàn)多種文件上傳薪介,下載功能祠饺,保存cookie等等功能,可以期待后續(xù)的文章汁政。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末道偷,一起剝皮案震驚了整個(gè)濱河市缀旁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌试疙,老刑警劉巖诵棵,帶你破解...
    沈念sama閱讀 219,039評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異祝旷,居然都是意外死亡履澳,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門怀跛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)距贷,“玉大人,你說(shuō)我怎么就攤上這事吻谋≈一龋” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,417評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵漓拾,是天一觀的道長(zhǎng)阁最。 經(jīng)常有香客問(wèn)我,道長(zhǎng)骇两,這世上最難降的妖魔是什么速种? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,868評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮低千,結(jié)果婚禮上配阵,老公的妹妹穿的比我還像新娘。我一直安慰自己示血,他們只是感情好棋傍,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著难审,像睡著了一般瘫拣。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上告喊,一...
    開(kāi)封第一講書(shū)人閱讀 51,692評(píng)論 1 305
  • 那天拂铡,我揣著相機(jī)與錄音,去河邊找鬼葱绒。 笑死,一個(gè)胖子當(dāng)著我的面吹牛斗锭,可吹牛的內(nèi)容都是我干的地淀。 我是一名探鬼主播,決...
    沈念sama閱讀 40,416評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼岖是,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼帮毁!你這毒婦竟也來(lái)了实苞?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,326評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤烈疚,失蹤者是張志新(化名)和其女友劉穎黔牵,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體爷肝,經(jīng)...
    沈念sama閱讀 45,782評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡猾浦,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了灯抛。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片金赦。...
    茶點(diǎn)故事閱讀 40,102評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖对嚼,靈堂內(nèi)的尸體忽然破棺而出夹抗,到底是詐尸還是另有隱情,我是刑警寧澤纵竖,帶...
    沈念sama閱讀 35,790評(píng)論 5 346
  • 正文 年R本政府宣布漠烧,位于F島的核電站,受9級(jí)特大地震影響靡砌,放射性物質(zhì)發(fā)生泄漏已脓。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 331
  • 文/蒙蒙 一乏奥、第九天 我趴在偏房一處隱蔽的房頂上張望摆舟。 院中可真熱鬧,春花似錦邓了、人聲如沸恨诱。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,996評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)照宝。三九已至,卻和暖如春句葵,著一層夾襖步出監(jiān)牢的瞬間厕鹃,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,113評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工乍丈, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留剂碴,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,332評(píng)論 3 373
  • 正文 我出身青樓轻专,卻偏偏與公主長(zhǎng)得像忆矛,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 自己備忘,隨便寫(xiě) android網(wǎng)絡(luò)框架源碼解析及對(duì)比 android常用網(wǎng)絡(luò)框架對(duì)比 Volley: 特點(diǎn) 基于...
    幻海流心閱讀 1,464評(píng)論 0 4
  • 前言 如果看Retrofit的源碼會(huì)發(fā)現(xiàn)其實(shí)質(zhì)上就是對(duì)okHttp的封裝催训,使用面向接口的方式進(jìn)行網(wǎng)絡(luò)請(qǐng)求洽议,利用動(dòng)態(tài)...
    李某人吖閱讀 2,042評(píng)論 0 0
  • 在開(kāi)發(fā)Android APP時(shí),肯定會(huì)使用到Http請(qǐng)求與服務(wù)器通信漫拭,上傳或下載數(shù)據(jù)等功能亚兄。目前開(kāi)源的Http請(qǐng)求...
    wangling90閱讀 478評(píng)論 0 0
  • github地址挑宠,歡迎大家提交更新菲盾。 express() express()用來(lái)創(chuàng)建一個(gè)Express的程序。ex...
    Programmer客棧閱讀 2,525評(píng)論 0 1
  • 見(jiàn) 真的發(fā)現(xiàn)這件事不容易做到各淀,特別是做好更不容易懒鉴。但是既然已經(jīng)上路就不會(huì)回頭。有人說(shuō)只要路是對(duì)的碎浇,哪怕慢點(diǎn)也沒(méi)關(guān)系...
    繆培閱讀 220評(píng)論 0 0