Retrofit2.0和Rxjava结合使用的简单记录
2019獨角獸企業重金招聘Python工程師標準>>>
Gradle的配置(該配置是針對rxjava1.x的)
compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'compile 'com.squareup.retrofit2:adapter-rxjava:2.0.0-beta4'//okhttp log 工具compile 'com.squareup.okhttp3:logging-interceptor:3.1.2'compile 'com.google.code.gson:gson:2.5'compile 'io.reactivex:rxandroid:1.1.0'compile 'io.reactivex:rxjava:1.1.0'compile 'com.squareup.retrofit2:retrofit:2.0.0-beta4'##常用的注解
@Path:該注解寫在方法中的參數類型(String)前面;用于指定@POST()或者@GET()請求中括號中的參數;該參數中不允許存在 斜杠 , 即只能表示一級,類似"目錄"; 可以把所有的路徑都存在一個類中,在@Post()的括號中引用這個路徑,這樣@Path就不需要使用;除非相同路徑下都是最后一級不相同,可以使用該注解。
@ Url :該注解寫在方法的參數類型前面;表示完整的Url。
@Query:用于自動拼接URL ?id=3&name=zhangsan&age=24;Post和Get請求中都可以使用
@QueryMap :傳入一個Map類型,自動拼接URL;Post和Get請求中都可以使用
@FormUrlEncoded 和Post一起使用;提交沒有文件的表單數據;和參數注解@Field和@FieldMap配合使用
@ Field:用于POST請求中,輸入拼接的請求體鍵值對;不帶文件上傳的表單提交
@ FieldMap :用于POST請求中,輸入拼接的請求體鍵值對的Map對象;不帶文件上傳的表單提交
@Streaming:下載文件必須要加上這個,保證下載的內容不會一下子都加載到內存中去;表示和服務器是長連接,會邊下載流,邊處理(比如寫入存儲器中),使得內存不會有一直持有所有的流數據。
@Multipart:提交帶有文件的表單使用;配合參數注解@Part和@PartMap使用;@PartMap的類型是 <String,RequestBody>
@Part,@PartMap: 用于POST文件上傳 @PartMap接受的數據類型是HashMap<String,RequestBody> @Part用法:@Part("xxx") RequestBody body
@Body 如果上傳的內容不是用@MultiPart來修飾的,也不是要傳遞鍵值對。參數中不能用@Part或者@PartMap來修飾。此時選擇用@Body;比如傳遞一個json字符串給服務器,此時就需要body,還需要改一下Header
關于文件的上傳: 參見 :http://blog.csdn.net/zhangxing52077/article/details/52830045 文件的下載可以使用 RxDownload
@Body:POST請求中的參數
@RequestBody
okhttp3.Media的常見type類型
eg: RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"), jsonString);
text/html : HTML格式 text/plain :純文本格式
text/xml : XML格式 image/gif :gif圖片格式
image/jpeg :jpg圖片格式 image/png:png圖片格式 以application開頭的媒體格式類型:
application/xhtml+xml :XHTML格式 application/xml : XML數據格式 application/atom+xml :Atom XML聚合格式
application/json : JSON數據格式 application/pdf :pdf格式
application/msword : Word文檔格式 application/octet-stream : 二進制流數據(如常見的文件下載) application/x-www-form-urlencoded : <form encType=””>中默認的encType,form表單數據被編碼為key/value格式發送到服務器(表單默認的提交數據的格式)
另外一種常見的媒體格式是上傳文件之時使用的: multipart/form-data : 需要在表單中進行文件上傳時,就需要使用該格式
@Headers :注解設置固定的請求頭,所有請求頭不會相互覆蓋,即使名字相同。
@Headers("Cache-Control: max-age=640000") @GET("widget/list") Call<List<Widget>> widgetList(); // 注意Headers括號中的鍵值對,冒號后面有一個空格!!!! @Headers({ "Accept: application/vnd.github.v3.full+json","User-Agent: Retrofit-Sample-App"}) @GET("users/{username}")Call<User> getUser(@Path("username") String username);@Header 使用 @Header 注解動態更新請求頭,匹配的參數必須提供給 @Header ,若參數值為 null ,這個頭會被省略,否則,會使用參數值的 toString 方法的返回值。
@GET("user") Call<User> getUser(@Header("Authorization") String authorization)獲取Retrofit的實例
public class RetrofitClient {private static final String TAG = "RetrofitClient";// private static final String BASE_URL ="https://api.douban.com/v2/movie/";private static OkHttpClient client = new OkHttpClient.Builder().addInterceptor(new Interceptor() {@Overridepublic Response intercept(Chain chain) throws IOException { // Log.v(TAG,chain.connection().route().address().toString());Log.v(TAG,chain.request().url().toString());Request.Builder builder = chain.request().newBuilder();//添加共同的頭信息 // builder.addHeader("token", "abc");return chain.proceed(builder.build());}}).connectTimeout(15, TimeUnit.SECONDS).readTimeout(15, TimeUnit.SECONDS).build();private static class Holder{private static Retrofit retrofit = new Retrofit.Builder().addCallAdapterFactory(RxJavaCallAdapterFactory.create()).addConverterFactory(GsonConverterFactory.create()).addConverterFactory(StringConverterFactory.create()).baseUrl(UrlConst.BASE_URL).client(client).build();}public static Retrofit getRetrofitInstance() {return Holder.retrofit;}private static Retrofit retrofit2;public static Retrofit getStringRetrofitInstance(String url) {retrofit2 = new Retrofit.Builder().addCallAdapterFactory(RxJavaCallAdapterFactory.create()).addConverterFactory(StringConverterFactory.create()).baseUrl(url).client(client).build();return retrofit2;}public static Retrofit retrofit3;public static Retrofit getRetrofitInstance(String url){retrofit3 = new Retrofit.Builder().addCallAdapterFactory(RxJavaCallAdapterFactory.create()).addConverterFactory(StringConverterFactory.create()).baseUrl(url).client(client).build();return retrofit3;} }創建Service的接口
GET請求
//具體的網絡url : 舉例子:https://api.douban.com/v2/movie/top250?start=2&count=4 public interface ApiService {@GET("top250")Observable<Entity> getMovies(@Query("start") int start,@Query("count") int count); } // 最好這么寫,參數用變量代替 public interface ApiService {@GET("{url}")Observable<Entity> getMovies(@Path("url") String url, @Query("start") int start, @Query("count") int count); }POST請求
public interface MovieService { //獲取豆瓣Top250 榜單 @FormUrlEncoded@POST("top250") Observable<MovieSubject> getTop250(@Field("start") int start, @Field("count") int count); }關于Post請求需要注意的幾個地方: 必須要有@FormUrlEncoded 配合 Filed使用時下載文件的GET請求
//必須要加上@Streaming,不然會把下載的東西全部讀到內存中去@Streaming@GETObservable<ResponseBody> downloadFile(@Url String url);寫入ReponseBody到文件系統
/*** 將ResponseBody中的內容保存到本地路徑 ;該路徑必須已經存在** @param body* @param localPath*/public static void writeResponseBodyToDisk(ResponseBody body, String localPath) {File file = new File(localPath);InputStream is = null;OutputStream os = null;long totalLength = body.contentLength();long currentLength = 0;double rate = 0;byte[] bytes = new byte[4096];try {os = new FileOutputStream(file);is = body.byteStream();int length = -1;while ((length = is.read(bytes)) != -1) {os.write(bytes, 0, length);currentLength += length;rate = currentLength * 1.0 / totalLength;}os.flush();} catch (IOException e) {e.printStackTrace();} finally {try {if (is != null) {is.close();}if (os != null) {os.close();}} catch (IOException e) {e.printStackTrace();}}}踩過的坑:
1.Post請求中
//獲取 任務@POST("index.php/machine/{url}")Observable<String> getTask(@Path("url") String url, @Body RequestBody requestBody);注解Post的括號中如果有引用方法的url時,那么方法中的url不能包括斜杠 / ,也不能包括問號 ? 因為斜杠 / 會被轉義為 %2F ; ? 會被轉義為 %3F ;斜杠和問號只有寫在@POST的括號中才不會被轉義。
2.Post請求上傳多個文件和其他字符串參數 文件上傳可以用兩種方式來做: 1.使用MultipartBody.Part 類型修飾在函數的文件參數前面;文件的參數和字符串參數分開來做;字符串參數可以用@PartMap來包裹
RequestBody apkBody = RequestBody.create(MediaType.parse("multipart/form-data"),file_apk);MultipartBody.Part partApk = MultipartBody.Part.createFormData("apk_url",file_apk.getName(),apkBody);2.(用的少)使用@PartMap注解修飾參數類型前面 , 上傳多個文件,但是對創建文件的RequestBody做一步處理;這種方式其實是把多個文件和字符串都放在@PartMap修飾的HasMap<String,RequestBody>中即:
RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);RequestBody requestBody1 = RequestBody.create(MediaType.parse("multipart/form-data"), file1);Map<String, RequestBody> params = new HashMap<>();params.put(key+"\"; filename=\""+ file.getName(), requestBody);params.put(key1+"\"; filename=\""+ file1.getName(), requestBody1);3.如果服務器返回值不是一個json,而是一個字符串String。那么我們用的GsonConvertory的Retrofit就不可用了。需要自定義一個StringConvertory.
5.文件和參數同時上傳的時候會遇到參數的value如果是String,會有兩個雙引號在外面。原因是由于使用了 Map<String,String>的方式,可以使用Map<String,RequestBody>的方式來解決這個問題。
轉載于:https://my.oschina.net/u/3246345/blog/1488583
總結
以上是生活随笔為你收集整理的Retrofit2.0和Rxjava结合使用的简单记录的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Oracle apex 搭建
- 下一篇: POJ 1195 Mobile phon