Rxjava+Retrofit基礎學習

前段時間看了RxJava,發現跟他一起用的Retrofit,今天就把認識的他們倆個來總結梳理一下

一、什么是RxJava?(異步)

一個實現異步操作的庫

給android開發者的RxJava詳解

具體的看下這個鏈接,寫的超級詳細,超級好

二、什么是Retrofit?

網絡請求的封裝。

Android 網絡(四) Retrofit學習筆記

Retrofit 是 Square 公司出品的默認基于 OkHttp 封裝的一套 RESTful 網絡請求框架,不了解 RESTful 概念的不妨去搜索學習下,RESTful 可以說是目前流行的一套 api 設計的風格,并不是標準。Retrofit 的封裝可以說是很強大,里面涉及到一堆的設計模式,你可以通過注解直接配置請求,你可以使用不同的 http 客戶端,雖然默認是用 http ,可以使用不同 Json Converter 來序列化數據,同時提供對 RxJava 的支持,使用Retrofit + OkHttp + RxJava + Dagger2可以說是目前比較潮的一套框架,但是需要有比較高的門檻。

Retrofit與picasso一樣都是在okhttp基礎之上做的封裝,項目中可以直接用了。Retrofit因為也是Square出的,所以大家可能對它更崇拜些。Retrofit跟Volley是一個套路,但解耦的更徹底:比方說通過注解來配置請求參數,通過工廠來生成CallAdapter,Converter,你可以使用不同的請求適配器(CallAdapter), 比方說RxJava,Java8, Guava。你可以使用不同的反序列化工具(Converter),比方說json, protobuff, xml, moshi等等。炒雞解耦,里面涉及到超多設計模式,個人覺得是很經典的學習案例。雖然支持Java8, Guava你可能也不需要用到。xml,protobuff等數據格式你也可能不需要解析。but,萬一遇到鬼了呢。至于性能上,個人覺得這完全取決于請求client,也就是okhttp的性能,跟這些封裝工具沒太大關系。

Retrofit 是一個 RESTful 的 HTTP 網絡請求框架的封裝。注意這里并沒有說它是網絡請求框架,主要原因在于網絡請求的工作并不是 Retrofit 來完成的。Retrofit 2.0 開始內置 OkHttp,前者專注于接口的封裝,后者專注于網絡請求的高效,二者分工協作,宛如古人的『你耕地來我織布』,小日子別提多幸福了。

我們的應用程序通過 Retrofit 請求網絡,實際上是使用 Retrofit 接口層封裝請求參數、Header、Url 等信息,之后由 OkHttp 完成后續的請求操作,在服務端返回數據之后,OkHttp 將原始的結果交給 Retrofit,后者根據用戶的需求對結果進行解析的過程。講到這里,你就會發現所謂 Retrofit,其實就是 Retrofitting OkHttp 了。

三、引用例子1

1、添加依賴

compile'com.squareup.retrofit2:retrofit:2.1.0' ? ? ? ? ? ? ? ? ? //引入retrofit所用的依賴

compile'com.squareup.retrofit2:converter-gson:2.1.0' ? ? ?//處理gson格式的數據,我們需要一個轉換器,需要導入這個依賴

compile'com.squareup.retrofit2:adapter-rxjava:2.1.0' ? ? ? ?//這兩個是我們需要配合Rxjava使用所添加的依賴

compile'io.reactivex:rxandroid:1.0.1'

2、添加權限

毫不疑問,我們現在學習的是網絡請求框架,自然需要添加網絡請求的權限

<uses-permission android:name="android.permission.INTENET"

3、重要的來啦

我們這是一個很簡單的demo,獲取登錄信息,接口為:https://api.github.com/users/{user}

定義一個接口包service

第一個接口

public interfaceLoginService {

@GET("/users/{user}")

Call<LoginModel>login(@Path("user") String user);

}

GET的意思是發送一個GET請求,請求的地址是:baseUrl+"/users/{user}"。{user}類似于占位符的作用,具體類型由 repo(@Path("user") String user) 指定,這里表示 {user} 將是一段字符串。

Call<LoginModel>是一個請求對象,<LoginModel>表示返回結果,是一個LoginModel類型的實例。

public class LoginModel{

privateString login;

publicStringgetLogin() {

returnlogin;?

}publicvoidsetLogin(String login) {

this.login = login;?

}}

接下來構造一個retrofit對象

Retrofit retrofit =newRetrofit.Builder()

.baseUrl("https://api.github.com")

.addConverterFactory(GsonConverterFactory.create())

.build();

注意這里添加的 baseUrl 和 GsonConverter,前者表示要訪問的網站,后者是添加了一個JSON轉換器。

創建API接口對象

LoginService service = retrofit.create(LoginService.class);

Call modelCall = service.login("lslolly");

注意這里的 .login("lslolly") 取代了前面的 {user}。到這里,我們要訪問的地址就成了:

https://api.github.com/users/lslolly

最后就可以發請求了

modelCall.enqueue(newCallback() {

@Override

public voidonResponse(Call call,Response response) {

Toast.makeText(MainActivity.this,"請求正確的結果是:"+response.body().getLogin(),Toast.LENGTH_LONG).show();

tv_result.setText("請求結果為:"+response.body().getLogin());

}

@Override

public voidonFailure(Call call,Throwable t) {

Toast.makeText(MainActivity.this,"請求錯誤的結果是:"+t.getMessage(),Toast.LENGTH_LONG).show();

}

下面說下POST請求參數設置

POST 的請求與 GET 請求不同,POST 請求的參數是放在請求體內的。所以當我們要為 POST 請求配置一個參數時,需要用到 @Body 注解:

Call<LoginModel>post(@Body User user);//這里的 User 類型是需要我們去自定義的:

public class User{?

publicString username;?

publicString password;

publicUser(String username,String password){

this.username = username;this.password = password;

}

//最后在獲取請求對象時:

User user =newUser("lslolly","123456");

Call<LoginModel> model = service.post(user);

//完整代碼實例如下

Retrofit retrofit =newRetrofit.Builder()

.baseUrl("https://api.github.com")

.addConverterFactory(GsonConverterFactory.create())

.build();

LoginService service = retrofit.create(LoginService.class);

Call<LoginModel>model =service.post(newUser("lolly","111111"));

model.enqueue(newCallback() {

@Override

public voidonResponse(Call call,Response response) {

Toast.makeText(MainActivity.this,"請求正確的結果是:"+response.body().getLogin(),Toast.LENGTH_LONG).show();

tv_result1.setText("請求結果為:"+response.body().getLogin());

}

@Override

public void onFailure(Call call,Throwable t) {

Toast.makeText(MainActivity.this,"請求錯誤的結果是:"+t.getMessage(),Toast.LENGTH_LONG).show();

}

});

四、例二

參考Retrofit使用教程(一)

使用的是百度的API Store提供的API,地址在此:手機號碼歸屬地__API服務_API服務_API Store.

1.設置model

訪問該API返回的數據格式如下:

{? ? "errNum":0,? ?

"retMsg":"success",? ?

"retData": {? ? ? ?

"phone":"15210011578",?

?"prefix":"1521001",??

"supplier":"移動", ? ? ??

"province":"北京",? ? ? ?

"city":"北京",? ? ? ?

"suit":"152卡"}

}

根據返回結果我們創建數據對象PhoneResult,如下:

publicclassPhoneResult{/**

* errNum : 0

* retMsg : success

* retData : {"phone":"15210011578","prefix":"1521001","supplier":"移動","province":"北京","city":"北京","suit":"152卡"}

*/privateinterrNum;privateString retMsg;/**

* phone : 15210011578

* prefix : 1521001

* supplier : 移動

* province : 北京

* city : 北京

* suit : 152卡

*/

private RetDataEntity retData;

public void setErrNum(interrNum) {this.errNum = errNum;? ? }

public void setRetMsg(String retMsg) {this.retMsg = retMsg;? ? }publicvoidsetRetData(RetDataEntity retData) {this.retData = retData;? ? }publicintgetErrNum() {returnerrNum;? ? }publicStringgetRetMsg() {returnretMsg;? ? }publicRetDataEntitygetRetData() {returnretData;? ? }publicstaticclassRetDataEntity{privateString phone;privateString prefix;privateString supplier;privateString province;privateString city;privateString suit;publicvoidsetPhone(String phone) {this.phone = phone;? ? ? ? }publicvoidsetPrefix(String prefix) {this.prefix = prefix;? ? ? ? }publicvoidsetSupplier(String supplier) {this.supplier = supplier;? ? ? ? }publicvoidsetProvince(String province) {this.province = province;? ? ? ? }publicvoidsetCity(String city) {this.city = city;? ? ? ? }publicvoidsetSuit(String suit) {this.suit = suit;? ? ? ? }publicStringgetPhone() {returnphone;? ? ? ? }publicStringgetPrefix() {returnprefix;? ? ? ? }publicStringgetSupplier() {returnsupplier;? ? ? ? }publicStringgetProvince() {returnprovince;? ? ? ? }publicStringgetCity() {returncity;? ? ? ? }publicStringgetSuit() {returnsuit;? ? ? ? }? ? }}

2.構造接口

public interface PhoneService{? ?

@GET("/apistore/mobilenumber/mobilenumber")? ?

Call<PhoneModel>getResult(@Header("apikey") String apikey, @Query("phone") String phone);}

3.使用

privatestaticfinalString BASE_URL ="http://apis.baidu.com";privatestaticfinalString API_KEY ="8e13586b86e4b7f3758ba3bd6c9c9135";privatevoidquery(){//1.創建Retrofit對象Retrofit retrofit =newRetrofit.Builder()? ? ? ? ? ? .addConverterFactory(GsonConverterFactory.create())//解析方法.baseUrl(BASE_URL)//主機地址.build();//2.創建訪問API的請求PhoneService service = retrofit.create(PhoneService.class);? ? Call call = service.getResult(API_KEY, phoneView.getText().toString());//3.發送請求call.enqueue(newCallback() {? ? ? ? @OverridepublicvoidonResponse(Call call, Response response) {//4.處理結果if(response.isSuccess()){? ? ? ? ? ? ? ? PhoneResult result = response.body();if(result !=null){? ? ? ? ? ? ? ? ? ? PhoneResult.RetDataEntity entity = result.getRetData();? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? }? ? ? ? @OverridepublicvoidonFailure(Call call, Throwable t) {? ? ? ? }? ? });}

四、query,head

參考Retrofit使用教程(二)

1.query

//如12306的查詢接口https://kyfw.12306.cn/otn/lcxxcx/query?//purpose_codes=ADULT&queryDate=2016-03-18&from_station=BJP&to_station=CDW,寫法如下:@GET("/otn/lcxxcx/query")Callquery(@Query("purpose_codes")Stringcodes, @Query("queryDate")Stringdate,? ? @Query("from_station")Stringfrom, @Query("to_station")Stringto)

2.head

//比如要更新某個賬戶信息,其接口地址為/info,需要帶的Header有設備信息device,//系統版本version,還要帶請求參數要更新賬戶的id,代碼如下:@POST("/info")Call updateInfo(@Header("device")Stringdevice, @Header("version")intversion,? ? ? ? ? ? ? ? ? ? ? ? @Field("id")Stringid);

五、Retrofit中使用RxJava

參考Retrofit使用教程(三):Retrofit與RxJava初相逢

//使用RxJava我們則返回一個可被觀測的PhoneResult:Observable,如下:

@GET("/apistore/mobilenumber/mobilenumber")ObservablegetPhoneResult(@Header("apikey") String apikey,? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? @Query("phone") String phone);//為了能返回此對象,我們需要在創建Retrofit對象時添加一個RxJava對象的Adapter來自動完成:Retrofit retrofit =newRetrofit.Builder()? ? ? ? .baseUrl(BASE_URL)? ? ? ? .addCallAdapterFactory(RxJavaCallAdapterFactory.create())? ? ? ? .addConverterFactory(GsonConverterFactory.create())? ? ? ? .build();//獲取手機的歸屬地phoneService.getPhoneResult(PhoneApi.API_KEY, number)? ? ? ? .subscribeOn(Schedulers.newThread())//子線程訪問網絡.observeOn(AndroidSchedulers.mainThread())//回調到主線程.subscribe(newObserver() {? ? ? ? ? ? @OverridepublicvoidonCompleted() {}? ? ? ? ? ? @OverridepublicvoidonError(Throwable e) {}? ? ? ? ? ? @OverridepublicvoidonNext(PhoneResult result) {if(result !=null&& result.getErrNum() ==0) {? ? ? ? ? ? ? ? ? ? PhoneResult.RetDataEntity entity = result.getRetData();? ? ? ? ? ? ? ? ? ? resultView.append("地址:"+ entity.getCity());? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? });}


好啦,簡單易懂的敘述就到此為止啦,寶寶要去練習封裝啦!完整demo如下:

demo地址

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,406評論 6 538
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,034評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,413評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,449評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,165評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,559評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,606評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,781評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,327評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,084評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,278評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,849評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,495評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,927評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,172評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,010評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,241評論 2 375

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,692評論 25 708
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,807評論 18 139
  • 前言RxJava和Retrofit也火了一段時間了,不過最近一直在學習ReactNative和Node相關的姿勢,...
    AFinalStone閱讀 558評論 0 0
  • 我從去年開始使用 RxJava ,到現在一年多了。今年加入了 Flipboard 后,看到 Flipboard 的...
    Jason_andy閱讀 5,552評論 7 62
  • 讀書:聽書《混亂》《博羅奔尼撒戰爭》 修改:閱讀講解音樂調整, 點評:作文一篇 彈琴:20分鐘 會議總結回饋:永林...
    躲進小樓看燈火閱讀 140評論 0 0