Retrofit2學(xué)習(xí)筆記-1

什么是Retrofit2

Retrofit是一個給Android和Java用的類型安全的HTTP客戶端俐东,它將網(wǎng)絡(luò)請求封裝成接口虏辫,并采用注解的形式聲明請求锈拨,由Retrofit自動生成接口實現(xiàn)對象給開發(fā)者調(diào)用。

Retofit2的入門

  1. 引用Retrofit2
    Gradle引用
    compile 'com.squareup.retrofit2:retrofit:2.1.0'
    Maven引用
<dependency>  
<groupId>com.squareup.retrofit2</groupId>  
<artifactId>retrofit</artifactId>  
<version>2.1.0</version>  
</dependency>
  1. Retrofit2入門
    接下來我們一步一步的學(xué)習(xí)使用Retrofit2的使用娄昆。
  • 創(chuàng)建Retrofit2實例
Retrofit retrofit = new Retrofit.Builder().baseUrl("http://wthrcdn.etouch.cn/").build();

創(chuàng)建Retrofit2實例時需要通過Retrofit.Builder方法,并調(diào)用baseUrl方法設(shè)置根URL萌焰。Retrofit2的baseUlr必須以/結(jié)束谷浅,不然會拋出一個IllegalArgumentException。

  • 定義一個和HTTP的API對應(yīng)的接口
    /** * 天氣服務(wù)     */    
public interface WeatherService {
        @GET("weather_mini")
        Call<WeatherBean> getWeatherInfo(@Query("city") String city);
    }
  • 生成網(wǎng)絡(luò)請求接口的對象
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://wthrcdn.etouch.cn/")
.addConverterFactory(GsonConverterFactory.create(gson))//這塊定義了一個轉(zhuǎn)換器撼玄,之后會講解
.build();
WeatherService service = retrofit.create(WeatherService.class);
  • 調(diào)用實現(xiàn)的方法來進行同步或異步的HTTP請求
Call<WeatherBean> call1 = service.getWeatherInfo("沈陽");
//異步請求
call1.enqueue(new Callback<WeatherBean>() {
    @Override
    public void onResponse(Call<WeatherBean> call, Response<WeatherBean> response) {
        Log.d("Retrofit2Example", response.body().getDesc());
    } 
   @Override
    public void onFailure(Call<WeatherBean> call, Throwable t) {
        Log.d("Retrofit2Example", t.getMessage()); 
   }});
try {    
//同步請求    
Response<WeatherBean> response = call1.execute();    
if (response.isSuccessful()) {
         Log.d("Retrofit2Example", response.body().getDesc());    
       }
} catch (IOException e) {    
         e.printStackTrace();
}

以上就是一個非常簡單的GET請求掌猛,可以看到通過Retrofit2的create()方法生成網(wǎng)絡(luò)接口的實現(xiàn)對象留潦,之后調(diào)用具體的接口調(diào)用方法會生成一個請求對應(yīng)的Call對象辣往,在這個時候請求并沒有發(fā)送出去殖卑,接下來調(diào)用Call對象的enqueue或者execute方法實現(xiàn)異步和同步的網(wǎng)絡(luò)請求。

  1. 詳細分析每一步
  • Retrofit2對象的創(chuàng)建
Retrofit retrofit = new Retrofit.Builder().baseUrl("http://wthrcdn.etouch.cn/").build();

可以看到我們可以使用Retrofit.Builder().build()這個方法創(chuàng)建一個Retrofit2對象许起,在創(chuàng)建的時候還可以使用baseUrl()方法為Retrofit2對象設(shè)置一個根路徑。這塊很好理解惦积,那么我們再介紹一下Retrofit2對象創(chuàng)建的時候還可以做的一些操作猛频。
1.首先介紹一下轉(zhuǎn)換器,轉(zhuǎn)換器顧名思義就是將服務(wù)端返回的Response進行轉(zhuǎn)換睦柴。在默認情況下Retrofit只支持將HTTP的響應(yīng)體轉(zhuǎn)換換為ResponseBody毡熏。比如要用Gson解析的話就需要添加依賴并使用addConverterFactory方法設(shè)置轉(zhuǎn)換器。

<!-- 引入gson -->
compile 'com.squareup.retrofit2:converter-gson:2.0.2'
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd hh:mm:ss").create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://wthrcdn.etouch.cn/")
.addConverterFactory(GsonConverterFactory.create(gson))
.build();

上面的代碼首先創(chuàng)建了一個gson對象狱窘,之后再創(chuàng)建retrofit對象的時候使用addConverterFactory方法設(shè)置了轉(zhuǎn)換器财搁。經(jīng)過這個設(shè)置之后呢我們在之后的請求中就可以使用泛型去作為請求體或者返回值了。

    /** * 天氣服務(wù)     */    
public interface WeatherService {
        @GET("weather_mini")
        Call<WeatherBean> getWeatherInfo(@Query("city") String city);
    }

類似這塊的代碼幻馁,返回值就是一個DTO越锈,我們看一下這個DTO內(nèi)部代碼。

public class WeatherBean {
    private String desc;
    private int status;
    private Data data;
    public void setDesc(String desc) {
        this.desc = desc;
    }
    public String getDesc() {
        return this.desc;
    }
    public void setStatus(int status) {
        this.status = status;
    } 
   public int getStatus() {
        return this.status;
    } 
   public void setData(Data data) {
        this.data = data;
    }
    public Data getData() {
        return this.data;
    }
}

當(dāng)我們設(shè)置了gson轉(zhuǎn)換器之后服務(wù)端返回的json格式的字符串就會被轉(zhuǎn)換成相應(yīng)的對象了稀拐。當(dāng)然如果你沒有設(shè)置轉(zhuǎn)換器的話這塊的泛型就是默認的ResponseBody了丹弱。

    /** * 天氣服務(wù)     */    
public interface WeatherService {
        @GET("weather_mini")
        Call<ResponseBody> getWeatherInfo(@Query("city") String city);
    }
  • 自定義Converter
    retrofit自帶的轉(zhuǎn)換器:
    • Gson: com.squareup.retrofit2:converter-gson
    • Jackson:com.squareup.retrofit2:converter-jackson
    • Moshi:com.squareup.retrofit2:converter-moshi
    • Protobuf:com.squareup.retrofit2:converter-protobuf
    • Wire:com.squareup.retrofit2:converter-wire
    • Simple XML:com.squareup.retrofit2:converter-simplexml
    • Scalars(primitives,boxed,String):com.squareup.retrofit2:converter-scalars
      如果自帶的轉(zhuǎn)換器不能滿足我們的需要躲胳,這個時候我們就需要自定義一個轉(zhuǎn)換器Converter了。
public interface Converter<F, T> {
 // 實現(xiàn)從 F(rom) 到 T(o)的轉(zhuǎn)換
 T convert(F value) throws IOException;
 // 用于向Retrofit提供相應(yīng)Converter的工廠
 abstract class Factory {
 // 這里創(chuàng)建從ResponseBody向其它類型的Converter隆檀,如果不能轉(zhuǎn)換返回null
 // 主要用于對響應(yīng)體的處理
 public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
 return null;
 }
 // 在這里創(chuàng)建 從自定類型到RequestBody的Converter,不能處理就返回null,
 // 主要用于對Part泉坐、PartMap裳仆、Body注解的處理
public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
 return null;
 }
// 這里用于對Field、FieldMap纯丸、Header构捡、Path、Query勾徽、QueryMap注解的處理
 // Retrfofit對于上面的幾個注解默認使用的是調(diào)用toString方法
 public Converter<?, String> stringConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
 return null;
 }
 }
}

比如我們要定義Call<ResponseBody> 轉(zhuǎn)換為Call<String>的轉(zhuǎn)換器喘帚,那么對應(yīng)的F和T則分別對應(yīng)ResponseBodyString,我們定義一個StringConverter并實現(xiàn)Converter接口吹由。

public static class StringConverter implements Converter<ResponseBody, String> {
           public static final StringConverter INSTANCE = new StringConverter();
           @Override
           public String convert(ResponseBody value)throws IOException {
                 return value.string();
            }
}

還需要一個Factory來向Retrofit注冊StringConverter倾鲫。

public static class StringConverterFactory extends Converter.Factory {
           public static final StringConverterFactory INSTANCE = new StringConverterFactory();
           public static StringConverterFactory create() {
                return INSTANCE;
            }
            // 我們只關(guān)實現(xiàn)從ResponseBody 到 String 的轉(zhuǎn)換,所以其它方法可不覆蓋
            @Override
            public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
                 if (type == String.class) {
                      return StringConverter.INSTANCE;
                 }
                 //其它類型我們不處理隙疚,返回null就行
                 return null;
            }
}

好了磕道,之后我們再使用Retrofit.Builder.addConverterFactory向Retrofit注冊我們StringConverterFactory

Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://wthrcdn.etouch.cn/") // 如是有Gson這類的Converter 一定要放在其它前面
.addConverterFactory(StringConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();

這里addConverterFactory是有先后順序的伶丐,如果有多個ConverterFactory都支持同一種類型疯特,那么就是只有第一個才會被使用,而GsonConverterFactory是不判斷是否支持的啡彬,所以這里交換順序還會有一個異常拋出羹与,原因是類型不匹配∈樱現(xiàn)在只要返回值類型的泛型參數(shù)是String就會由我們的StringConverter處理往踢。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末峻呕,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子瘦癌,更是在濱河造成了極大的恐慌跷敬,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件斤寇,死亡現(xiàn)場離奇詭異拥褂,居然都是意外死亡,警方通過查閱死者的電腦和手機莫秆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門悔详,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人杯道,你說我怎么就攤上這事责蝠。” “怎么了霜医?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵肴敛,是天一觀的道長吗购。 經(jīng)常有香客問我砸狞,道長,這世上最難降的妖魔是什么踱启? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任研底,我火速辦了婚禮,結(jié)果婚禮上冠蒋,老公的妹妹穿的比我還像新娘。我一直安慰自己抖剿,他們只是感情好胚吁,可當(dāng)我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著孽拷,像睡著了一般半抱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上窿侈,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天史简,我揣著相機與錄音,去河邊找鬼圆兵。 笑死,一個胖子當(dāng)著我的面吹牛刀脏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播愈污,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼首装!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起簿盅,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎棚瘟,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體偎蘸,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年限书,在試婚紗的時候發(fā)現(xiàn)自己被綠了倦西。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡扰柠,死狀恐怖疼约,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情劝枣,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布舔腾,位于F島的核電站昙沦,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏采桃。R本人自食惡果不足惜懒熙,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一工扎、第九天 我趴在偏房一處隱蔽的房頂上張望衔蹲。 院中可真熱鬧,春花似錦舆驶、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至巨税,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間草添,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工促王, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留而晒,地道東北人。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓迅耘,卻偏偏與公主長得像监署,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子钠乏,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,512評論 2 359

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