Retrofit2.0 學(xué)習(xí)小記
來自官網(wǎng)的介紹:Retrofit turns your HTTP API into Java interface.Retrofit把HTTP API變成Java的接口。
1.基本用法
直接上代碼:比如我們使用豆瓣電影的Top250做測試鏈接,目標(biāo)地址為:https://api.douban.com/v2/movie/top250?start=0&count=10
導(dǎo)包:compile 'com.squareup.retrofit:retrofit:2.0.0-beta2'
首先要建這樣一個(gè)接口:
public interface MovieService{
@GET("top250")
Call<MovieEntity> getTopMovie(@Query("start")int start,@Query("count") int count);
}
然后你還需要創(chuàng)建一個(gè)Retrofit對象:
public static final String baseUrl="https://api.douban.com/v2/movie/";
Retrofit retrofit=new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
再用這個(gè)Retrofit對象創(chuàng)建一個(gè)MovieService對象:
MovieService movieService=retrofit.create(MovieService.class);
Call<MovieEntity> call=movieService.getTopMovie(0,10);
//call.enqueue()異步請求,call.execute()同步請求
call.enqueue(new Callback<MovieEntity>(){
@Override
public void onResponse(Call<MovieEntity> call, Response<MovieEntity> response) {
result_TV.setText(response.body().toString());
}
@Override
public void onFailure(Call<MovieEntity> call, Throwable t) {
result_TV.setText(t.getMessage());
}
});
在這邊還可以移除一個(gè)請求:
Retrofit 1.x版本沒有直接取消正在進(jìn)行中任務(wù)的方法的浊猾,在2.x的版本中,Service的模式變成Call的形式的原因是為了讓正在進(jìn)行的事務(wù)可以被取消纳寂。要做到這點(diǎn)滤愕,只需要調(diào)用call.cancel()厂僧。
以上就是Retrofit2.0的基本用法了,下面講講它的詳細(xì)用法:
1.關(guān)于各種網(wǎng)絡(luò)請求的service
下面分為GET胆绊、POST氨鹏、DELETE和PUT的請求,說明@Path压状、@Query仆抵、@QueryMap、@Body何缓、@Filed的用法肢础。
GET
1.一個(gè)簡單的get請求:
http://102.10.10.132/api/News
@GET("News") Call<NewsBean> getItem();
2.URL中帶有參數(shù):http://102.10.10.132/api/News/{資訊id}
@GET("News/{newsId}")
Call<NewsBean> getItem(@Path("newsId") String newsId);
3.參數(shù)在URL問號之后:http://102.10.10.132/api/News?newsId={資訊id}
@GET("News")
Call<NewsBean> getItem(@Query("newsId") String newsId);
或者帶有兩個(gè)參數(shù):http://102.10.10.132/api/News?newsId={資訊id}&type={類型}
@GET("News")
Call<NewsBean> getItem(@Query("newsId") String newsId,@Query("type") type);
4.多個(gè)參數(shù)在URL問號之后,且個(gè)數(shù)不確定:
http://102.10.10.132/api/News?newsId={資訊id}&type={類型}...
@GET("News")
Call<NewsBean> getItem(@QueryMap Map<String, String> map);
POST
1.需要補(bǔ)全URL碌廓,post的數(shù)據(jù)只有一條reason:
http://102.10.10.132/api/Comments/{newsId}
@FormUrlEncoded
@POST("Comments/{newsId}")
Call<Comment> reportComment(@Path("newsId") String commentId,@Field("reason") String reason);
2.需要補(bǔ)全URL,問號后加入access_token剩盒,post的數(shù)據(jù)只有一條reason:
http://102.10.10.132/api/Comments/{newsId}?access_token={access_token}
@FormUrlEncoded
@POST("Comment/{newsId}")
Call<Comment> reportComment(@Path("newsId") String commentId,@Query("access_token") String access_token,@Field("reason") String reason);
3.需要補(bǔ)全URL谷婆,問號后加入access_token,post一個(gè)body(對象):
http://102.10.10.132/api/Comments/{newsId}?access_token={access_token}
@FormUrlEncoded
@POST("Comment/{newsId}")
Call<Comment> reportComment(@Path("newsId") String commentId,@Query("access_token") String access_token,@Body CommentBean bean);
關(guān)于DELETE和PUT方式由于使用較少辽聊,這里就不舉例了纪挎,可自行g(shù)oogle
總結(jié):
@Path:URL問號之前的參數(shù)
@Query:URL問號后面的參數(shù)
@QueryMap:相當(dāng)于多個(gè)@Query
@Field:用于POST請求,提交單個(gè)數(shù)據(jù)
@Body:相當(dāng)于多個(gè)@Field,以對象的形式提交
若需要重新定義接口地址跟匆,可以使用@Url,例如:
@GET
Call<MovieEntity> getTopMovie(@Url String url,@Query("start")int start,@Query("count") int count);
關(guān)于解析
在Retrofit2.0中异袄,Converter不再包含在packeage中了,需要自己添加Converter玛臂,不然的話Retrofit只能接收字符串結(jié)果烤蜕。同樣的,Retrofit也不再依賴于Gson迹冤,如果你想接收json結(jié)果并解析成DAO讽营,你必須把GsonConverter作為一個(gè)獨(dú)立的依賴添加進(jìn)來:compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2' ,然后使用addConverterFactory(GsonConverterFactory.create())幫他添加進(jìn)來泡徙。
官方Converter modules列表
Gson: com.squareup.retrofit:converter-gson
Jackson: com.squareup.retrofit:converter-jackson
Moshi: com.squareup.retrofit:converter-moshi
Protobuf:com.squareup.retrofit:converter-protobuf
Wire: com.squareup.retrofit:converter-wire
Simple XML: com.squareup.retrofit:converter-simplexml
當(dāng)然也可以通過實(shí)現(xiàn)Converter.Factory接口來創(chuàng)建一個(gè)自定義的converter橱鹏。
2.Retrofit+RxJava(附上demo)
導(dǎo)包:
compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta2'
compile 'io.reactivex:rxandroid:1.1.0'
在創(chuàng)建Retrofit的過程添加以下代碼:
Retrofit retrofit=new Retrofit.Builder()
.baseUrl(baseUrl) .addConverterFactory(GsonConverterFactory.create())
//結(jié)合RxJava .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
這樣一來我們定義的Service返回值就不再是一個(gè)Call了,而是一個(gè)Observable堪藐,重新定義MovieService:
public interface MovieService {
@GET("top250")
Observable<MovieEntity> getTopMovie(@Query("start") int start, @Query("count") int count);
}
在網(wǎng)絡(luò)請求方法中改為:
//進(jìn)行網(wǎng)絡(luò)請求
private void getMovie(){
Retrofit retrofit = <span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">new</span></span> Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
MovieService movieService = retrofit.create(MovieService.class);
movieService.getTopMovie(<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-number"</span>><span class="hljs-number">0</span></span>, <span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-number"</span>><span class="hljs-number">10</span></span>)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">new</span></span> Subscriber<MovieEntity>() {
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-annotation"</span>>@Override</span>
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-function"</span>><span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">public</span></span> <span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">void</span></span> <span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-title"</span>>onCompleted</span><span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-params"</span>>()</span> </span>{
Toast.makeText(MainActivity.<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">this</span></span>, <span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-string"</span>><span class="hljs-string">"Get Top Movie Completed"</span></span>, Toast.LENGTH_SHORT).show();
}
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-annotation"</span>>@Override</span>
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-function"</span>><span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">public</span></span> <span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">void</span></span> <span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-title"</span>>onError</span><span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-params"</span>>(Throwable e)</span> </span>{
resultTV.setText(e.getMessage());
}
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-annotation"</span>>@Override</span>
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-function"</span>><span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">public</span></span> <span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">void</span></span> <span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-title"</span>>onNext</span><span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-params"</span>>(MovieEntity movieEntity)</span> </span>{
resultTV.setText(movieEntity.toString());
}
});
}
這就基本上完成了Retrofit和RxJava的結(jié)合莉兰,但是可以把創(chuàng)建Retrofit的過程封裝一下。可參考這篇文章,不錯(cuò)的一個(gè)例子