Retrofit2.0使用文檔

參考資料:

http://blog.csdn.net/u014165119/article/details/49280779
https://github.com/square/okhttp/tree/master/samples  OkHttp的Sample
http://blog.csdn.net/ljd2038/article/details/51189334   文件下載案例

系列文章資料:

這是我對(duì)Retorfit2.0源碼的一些解讀,有問(wèn)題希望大家指正
Retrofit2.0中的Builder模式
Retrofit2.0中的動(dòng)態(tài)代理模式
Retrofit2.0中的適配器模式
Retrofit2.0中的策略模式

一、為什么使用Retrofit2.0

(1).Retrofit2.0是由Square公司開(kāi)發(fā)的一個(gè)網(wǎng)絡(luò)請(qǐng)求框架,已經(jīng)成為Android開(kāi)發(fā)中非?;馃岬囊粋€(gè)庫(kù)。是Square公司對(duì)OkHttp進(jìn)行再次封裝的框架。

Paste_Image.png

Google在大概Android4.3(具體不太清楚了)的時(shí)候已經(jīng)不推薦使用HttpClient ,改為用推薦使用OkHttp,在6.0的時(shí)候更是刪除了HttpClient,Retrofit作為Square公司推出的對(duì)Okhttp再次封裝得庫(kù),無(wú)疑對(duì)OkHttp支持的更好。對(duì)比現(xiàn)在主流的網(wǎng)絡(luò)框架Volly,Volly針對(duì)不同的返回類型,需要調(diào)用不同的方法,傳入?yún)?shù)也非常麻煩,而Retrofit在調(diào)用一個(gè)接口時(shí),就像是在調(diào)用一個(gè)本地方法。同時(shí)Retrofit采用鏈?zhǔn)骄幊痰姆绞?,讓代碼的邏輯結(jié)構(gòu)更加清晰。Retrofit非常靈活,可以做到動(dòng)態(tài)的去配置Url。同時(shí)它非常適合RESTFUL API的形式。

示例服務(wù)端代碼:

@Controller
@EnableWebMvc
@RequestMapping(headers="Accept=*/*", 
 produces="application/json")

public class LoginController {

    @Resource
    LoginService service;// 自動(dòng)依賴注入
    @Resource
    LoginEntity userEntity;
    @Resource
    ResultEntity resultEntity;
    @RequestMapping(value = "login", method = RequestMethod.GET,produces = "application/json",headers="Accept=*/*")
    @ResponseBody
    public 
 ResultEntity login(HttpServletRequest
 request,HttpServletResponse response) {
        //拿到服務(wù)器端的參數(shù)
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        if (service.isExitsPeople(username, password)==1) {
            userEntity.setUsername(username);
            userEntity.setPassword(password);
            resultEntity.setIsSuccess(true);
            resultEntity.setMessage("登錄成功");
            resultEntity.setResult(userEntity);
            return  resultEntity;
        }else{
            resultEntity.setIsSuccess(false);
            resultEntity.setMessage("登錄失敗");
            resultEntity.setResult("");
            return resultEntity;
        }    
       //System.out.println("測(cè)試login方法是否成功" + service.getUserCount(username, password));
       // System.out.println("測(cè)試MyBatis使用是否成功" + service.isExitsPeople(username, password));
    }
}

示例Retrofit api的代碼

示例客戶端API代碼:
public interface LoginService {
@FormUrlEncoded
@POST("Member/Login")
    Call<UserModel>
loginApp(@Field("username") String name, @Field("password")
String pwd               
}

(2).它的請(qǐng)求速度非???br> 圖片來(lái)自:
http://blog.csdn.net/xiongge358/article/details/50990864

Paste_Image.png

示例代碼:

public
 class RetrofitClient {
    private Retrofit client;
    private String BaseUrl;
    /**
     * 初始化Retrofit的內(nèi)容
     */
    public RetrofitClient(String BaseUrl) {
        this.BaseUrl = BaseUrl;
        client = new Retrofit.Builder()     
 .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
 .addConverterFactory(GsonConverterFactory.create(
 .baseUrl(BaseUrl)
 .build();
    }
    public SmileAPI getSmileAPI() {
        return client.create(SmileAPI.class);
    }
    public WeatherAPI getWeatherAPI() {
        return client.create(WeatherAPI.class);
    }
}

二、配置Retrofit2.0

在Moudel的gradle中配置

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

同樣Retrofit也可以對(duì)OkHttp進(jìn)行自己的定制,所以如果需要定制OkHttp同樣可以引入Okhttp的庫(kù)

 compile 'com.squareup.okhttp3:okhttp:3.3.1'

三、使用Retrofit2.0

1.配置Retrofit

***baseUrl:****

  1. 默認(rèn)的服務(wù)器地址,Retrofit在進(jìn)行請(qǐng)求一個(gè)接口時(shí)會(huì)根據(jù)你填寫的 baseurl+方法名 去請(qǐng)求。

****addConverterFactory:****

添加返回?cái)?shù)據(jù)的解析方式,Retrofit支持多種格式的解析,xml,json,jackson,Moshi,Protobuf,wire等,添加對(duì)這些數(shù)據(jù)格式的支持同樣需要在Gradle中進(jìn)行依賴。這些依賴Square公司同樣提供了支持。
這里是Square提供的官方Converter modules列表。選擇一個(gè)最滿足你需求的。

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

****CallAdapter:****

Retrofit會(huì)將網(wǎng)絡(luò)請(qǐng)求的接口以回調(diào)的方式返回,我們通常會(huì)得到一個(gè)叫做Call<類型>的結(jié)果,如果我們需要返回其他的結(jié)果,例如RxJava形式的結(jié)果,需要對(duì)RxJava做支持。如果不需要特殊類型的返回結(jié)果,我們是不需要配置的。

****Client:****

通過(guò)該方法我們可以添加自己定制的OkHttp。
定制OkHttp

HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
        .addInterceptor(interceptor)
        .retryOnConnectionFailure(true)
        .connectTimeout(15, TimeUnit.SECONDS)
        .addNetworkInterceptor(mTokenInterceptor)
        .build();
//將定制的OkHttp加入到Retrofit中
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl(AppConfig.BASE_URL)
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
        .addConverterFactory(GsonConverterFactory.create(gson))
        .client(client)
        .build();
```
***Create:***
如果一切都配置好了,那么通過(guò)調(diào)用Create,并傳入你的接口方法類型,就可以請(qǐng)求服務(wù)端了。
使用Retrofit

####一、  定義請(qǐng)求的接口
Retrofit非常適合Restful API,它采用注解,加動(dòng)態(tài)代理的方式去請(qǐng)求一個(gè)服務(wù)。
1.     **定義你要請(qǐng)求的接口**

因?yàn)镽etrofit采用動(dòng)態(tài)代理的方式去請(qǐng)求一個(gè)接口,所以在定義我們需要請(qǐng)求的接口時(shí),我們需要定義一個(gè)接口,并添加相應(yīng)的注解,告訴Retrofit如何請(qǐng)求我們需要的接口。參數(shù)的返回類型默認(rèn)情況下需要通過(guò)Call方法進(jìn)行包裝。

```
public interface LoginService {
@FormUrlEncoded
@POST("Member/Login")
  Call<UserModel>loginApp(@Field("username") String name, @Field("password")String pwd  ,@Field("grid") String grid);
}
```
 

####二、   Retrofit的注解

**方法上的注解**

1.請(qǐng)求的類型
```
@POST
@GET
參數(shù):請(qǐng)求的方法,對(duì)應(yīng)接口文檔的方法名。
```
2.添加靜態(tài)的頭部協(xié)議
```
@Headers
例如:@Headers("Cache-Control: max-age=640000")
```
3.數(shù)據(jù)提交的方式
```
@FormUrlEncoded
添加該注解后,將會(huì)發(fā)送form-encode的數(shù)據(jù)類型
```
4.數(shù)據(jù)提交的方式
```
@Multipart
添加該注解后,將會(huì)發(fā)送Mulitipar類型的數(shù)據(jù)。
```
**參數(shù)注解**

```
1.@Part:如果你在方法注解上加入了@Multipart,那么對(duì)應(yīng)的方法參數(shù)必須要用該注解
```
 
```
2.@Field:如果你在方法注解上加入了@FormUrlEncoded注解,那么對(duì)應(yīng)的方法參數(shù)必須用該注解。
```
 
```
3.   @Body:如果傳遞的是一個(gè)序列化的參數(shù)
例如:@POST("users/new")
Call<User> createUser(@Body User user);
```
 

**Retrofit請(qǐng)求的Url同樣是可以動(dòng)態(tài)配置的。請(qǐng)求的URL可以在函數(shù)中使用替換塊和參數(shù)進(jìn)行動(dòng)態(tài)更新,替換塊是{ and }包圍的字母數(shù)字組成的字符串。
**

```
3.@Path :Url中有一段是需要?jiǎng)討B(tài)配置的時(shí)候
例如:
@GET("group/{id}/users")
List<User>
groupList(@Path("id") int groupId);

``` 
 
```
4.@Query 查詢參數(shù)
例如:
@GET("group/{id}/users")
```

```
List<User> groupList(@Path("id") int groupId,
@Query("sort") String sort);
```
 

5.復(fù)雜的參數(shù)同樣可以通過(guò)Map方式

```
例如:
@GET("group/{id}/users")
List<User>
groupList(@Path("id") int groupId, @QueryMap Map<String,
String> options);

 ```

 

####四、處理Call返回的參數(shù)

1. 如果我們定義好了接口。那么這個(gè)時(shí)候就可以調(diào)用create方法,并且傳入我們需要請(qǐng)求的接口類型,拿到返回值了。
使用Call:

例子:
```
 MyService service =retrofit.create(MyService.class);
 Call<ResultModel<UserInfoModel>>call = service.loginApp("","");
 Service.loginApp:就是執(zhí)行我們定義的方法,并且拿到返回值。
``` 

2. 接著我們使用Call:
```
call.enqueue(new Callback<Repo>() {
   @Override
public void onResponse(Response<UserInfoModel response) {
       // 通過(guò)reponse拿到結(jié)果
      UserModelInfo info=response.body();
    }  
     @Override
     public void onFailure(Throwable t) {  
   }
});
```
 

####五、Retrofit實(shí)現(xiàn)文件上傳(方式1)

1.使用@Mulitpart注解標(biāo)記接口 
2.@Part              注解標(biāo)記文件類型的參數(shù)
3.MultipartBody.Part   標(biāo)記文件的參數(shù)

 ```
public interface FileUploadService {  
 @Multipart
 @POST("upload")
 Call<ResponseBody> upload(@Part("description") RequestBody description,
                          @Part MultipartBody.Part file);
}
 ```

4.使用RequestBody包裝上傳文件

```
//構(gòu)建要上傳的文件
File file = new File(filename);
RequestBody requestFile =RequestBody.create(MediaType.parse("multipart/form-data"),file);
```
***注:MediaType.parse 參數(shù)代表上傳文件的類型(Content-Type)的類型,例如:如果是上傳的是圖片,可以寫成MediaType.parse("image/jpg")***


5.使用MultipartBody.Part對(duì)Request再次包裝

```
//構(gòu)建要上傳的文件
參數(shù)1:對(duì)應(yīng)的接口參數(shù)
參數(shù)2:上傳的文件名稱
參數(shù)3:包裝的RequestBody

MultipartBody.Part body = MultipartBody.Part.createFormData("aFile", file.getName(),
requestFile);
```
 

 

6.調(diào)用上傳方法:
```
Call<ResponseBody> call = service.upload(description,body);
```
####六、Retrofit實(shí)現(xiàn)文件上傳(方式2)

1.通過(guò)定義自己的FileConvertFactory,我們可以將File類型,不通過(guò)包裝,作為參數(shù)傳入。
```
public interface FileUploadService {     
@Multipart   
@POST("upload")                    //注意這里的參數(shù) "aFile" 之前是在創(chuàng)建MultipartBody.Part 的時(shí)候傳入的
Call<ResponseBody> upload(@Part("description") RequestBody description,       
@Part("aFile") File file);
}
```
 
####7.使用ConvertFactory進(jìn)行上傳

繼承Converter.Factory :
```
static class FileRequestBodyConverterFactory extends Converter.Factory {
@Override
public Converter<File, RequestBody> requestBodyConverter(Type type, Annotation[]
parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {   
return new FileRequestBodyConverter();
  }
}
static class FileRequestBodyConverter implements Converter<File, RequestBody> {
 @Override
  public RequestBody convert(File file) throws IOException {   
return RequestBody.create(MediaType.parse("application/otcet-stream"),file); 
 }
}
```
2.在配置Retrofit時(shí)加入我們自己的文件類型支持

```
.addConverterFactory(new
FileRequestBodyConverterFactory())
```

####七、文件下載

使用Okhttp的ReponseBody做為返回類型

示例代碼: 
```
Call<ResponseBody> call =mService.getFile();
call.enqueue(new Callback<ResponseBody>() {
    @Override
    public void onResponse(Call<ResponseBody> call, Response<ResponseBody>
response) {
       try {
            writeResponseBodyToDisk(MainActivity.this, response.body());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @Override
    public void
onFailure(Call<ResponseBody> call, Throwable t) {
        Log.e("H", "result
: " + t.toString());
    }
});
```
 

 

ReponseBody會(huì)拿到文件流,對(duì)拿到的文件流做處理
示例代碼:

```
public boolean writeResponseBodyToDisk(Context context, ResponseBody body) throws IOException {
    Log.d("tag","開(kāi)始下載"+"/"+body.contentType().toString());
    boolean flag = true;
    String type =
    body.contentType().toString();

 if (type.equals(".apk")) {
        mFileSuffix = ".apk";
    } else if (type.equals(".png")) {
        mFileSuffix = ".png";
   } 
 else if(type.equals(".jpg")) {
   mFileSuffix = ".jpg"; }
    if (type.equals(".zip")) {
        mFileSuffix = ".zip";
    }
    // 其他同上 自己判斷加入
    final String name ="guo"+System.currentTimeMillis() + mFileSuffix;
    final String path =Environment.getExternalStorageDirectory() + File.separator + name;
    /**
     * 寫入流
     */
    InputStream is = body.byteStream();
    File file = new File(path);
    FileOutputStream fos = new FileOutputStream(file);
    BufferedInputStream bis = new BufferedInputStream(is);
    byte[] buffer = new byte[1024];
    int len;
    while ((len = bis.read(buffer)) !=-1) {
        fos.write(buffer, 0, len);
        fos.flush();
    }
    fos.close();
    bis.close();
    is.close();
    Log.d("tag","下載完畢");
    return flag;
}
```
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容