版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
Retrofit結(jié)合RxJava使用指南Retrofit是一個(gè)當(dāng)前很流行的網(wǎng)絡(luò)請(qǐng)求庫(kù),官網(wǎng)的介紹是:"Type-safeHTTPclientforAndroidandJava".本文介紹Retrofit的使用.先介紹單獨(dú)使用Retrofit進(jìn)行網(wǎng)絡(luò)請(qǐng)求,后面主要介紹和RxJava結(jié)合的請(qǐng)求,有實(shí)例代碼.Retrofit單獨(dú)使用Setup首先在manifest中加上網(wǎng)絡(luò)權(quán)限:<uses-permissionandroid:name="android.permission.INTERNET"/>然后在app/build.gradle中加上依賴:compile'com.squareup.retrofit2:retrofit:2.1.0'compile'com.google.code.gson:gson:2.8.0'compile'com.squareup.retrofit2:converter-gson:2.1.0'準(zhǔn)備API和model類本例子中使用GithubAPI做請(qǐng)求.以Github的RootEndpoint為例:.首先,我們?cè)诿钚邪l(fā)送:curl或者在Postman發(fā)送這個(gè)請(qǐng)求,兩種方法都可以得到結(jié)果.這個(gè)請(qǐng)求返回的是一個(gè)json.利用這個(gè)網(wǎng)站:jsonschema2pojo,可以用json生成一個(gè)java類,比如上面這個(gè),我們給它起名字叫Endpoints.java.之后例子中的API都是這種方式,先發(fā)送請(qǐng)求得到j(luò)son,然后轉(zhuǎn)成java的model類.利用Retrofit發(fā)送請(qǐng)求并得到結(jié)果首先寫一個(gè)ServiceGenerator類,用于生成service:publicclassServiceGenerator{publicstaticfinalStringAPI_BASE_URL="";privatestaticOkHttpClient.BuilderhttpClient=newOkHttpClient.Builder();privatestaticRetrofit.Builderbuilder=newRetrofit.Builder().baseUrl(API_BASE_URL).addConverterFactory(GsonConverterFactory.create());publicstatic<S>ScreateService(Class<S>serviceClass){Retrofitretrofit=builder.client(httpClient.build()).build();returnretrofit.create(serviceClass);}}這里指定了我們的baseurl.createService()方法返回的是一個(gè)泛型.然后我們創(chuàng)建GithubService,注意這是一個(gè)接口:importcom.ddmeng.helloretrofit.data.models.Endpoints;importretrofit2.Call;importretrofit2.http.GET;importretrofit2.http.Url;publicinterfaceGitHubService{@GETCall<Endpoints>getAllEndpoints(@UrlStringurl);}這里@GET指定了是一個(gè)GET請(qǐng)求,因?yàn)槲覀冋?qǐng)求的就是baseurl,所以是這樣寫的.Endpoints類是這個(gè)請(qǐng)求所返回的json轉(zhuǎn)化的java類.好了,準(zhǔn)備工作做完了,現(xiàn)在就可以請(qǐng)求并得到結(jié)果:請(qǐng)求githubapi的rooturl,得到所有的endpoints:GitHubServicegitHubService=ServiceGenerator.createService(GitHubService.class);Call<Endpoints>endpointsCall=gitHubService.getAllEndpoints("");endpointsCall.enqueue(newCallback<Endpoints>(){@OverridepublicvoidonResponse(Call<Endpoints>call,Response<Endpoints>response){Endpointsendpoints=response.body();StringrepositoryUrl=endpoints.getRepositoryUrl();LogUtils.i(repositoryUrl);Toast.makeText(MainActivity.this,"repositoryurl:"+repositoryUrl,Toast.LENGTH_LONG).show();}@OverridepublicvoidonFailure(Call<Endpoints>call,Throwablet){}});說明:首先利用前面的ServiceGenerator來創(chuàng)建Service,然后調(diào)用接口中定義的getAllEndpoints()方法,此處傳入了空字符串,因?yàn)槲艺?qǐng)求的就是baseurl.同步和異步這里注意用Retrofit請(qǐng)求的返回值是Call<T>(后面我們還會(huì)介紹用RxJava的情形),泛型T是model類型,它有兩個(gè)方法:execute()是同步方法,返回Response<T>;enqueue()是異步方法,在上面的例子中用的就是這個(gè),在回調(diào)onResponse()中返回了Response<T>.ConverterConverter的作用:如果不指定Converter,默認(rèn)情況下Retrofit只能返回ResponseBody類型,加了Converter之后就可以返回我們定義的Model類型了.所以Converter替我們做了json->model的工作.本例子中ConverterFactory指定的是GsonConverterFactory.這里我們選的是GsonConverter,所以依賴的是com.squareup.retrofit2:converter-gson.Retrofit支持多種converters:Gson:com.squareup.retrofit2:converter-gsonJackson:com.squareup.retrofit2:converter-jacksonMoshi:com.squareup.retrofit2:converter-moshiProtobuf:com.squareup.retrofit2:converter-protobufWire:com.squareup.retrofit2:converter-wireSimpleXML:com.squareup.retrofit2:converter-simplexmlScalars(primitives,boxed,andString):com.squareup.retrofit2:converter-scalarsPath和參數(shù)從上面返回的endpoints可以看到,user_url是:/users/{user}這是一個(gè)帶path參數(shù)的url,我們發(fā)請(qǐng)求的時(shí)候在{user}處寫一個(gè)github用戶名,即可得到該用戶的信息,比如:/users/mengdd.那么用Retrofit如何處理呢?只需要在GithubService中增加一個(gè)方法,這樣寫:publicinterfaceGitHubService{@GETCall<Endpoints>getAllEndpoints(@UrlStringurl);@GET("users/{user}")Call<User>getUser(@Path("user")Stringuser);}使用時(shí)的方法完全一樣,不再贅述,同理,如果要在后面加參數(shù),可以用@Query.更多注解的例子見官方網(wǎng)站:RetrofitRetrofit+RxJavaRxJava近年來很流行,主要優(yōu)勢(shì)是流式操作,可以處理并行發(fā)送請(qǐng)求,使用靈活,線程切換容易.當(dāng)你要處理的邏輯比較復(fù)雜時(shí),就會(huì)發(fā)現(xiàn)使用RxJava的優(yōu)勢(shì).以我們的例子來說,當(dāng)前我們利用一個(gè)請(qǐng)求可以得到一個(gè)用戶的信息并顯示出來.如果我們想得到這個(gè)用戶的所有repo的所有者或者其他信息,所有他follow的人的信息,以及他們的repo的信息呢?這就需要發(fā)很多個(gè)請(qǐng)求,并且其中有些請(qǐng)求是并行發(fā)送的,如果按照前面的方法,不斷地在callback里面嵌套,那就太難看了.SetupwithRxJava添加RxJava依賴首先,添加RxJava和RxAndroid的依賴:compile'io.reactivex:rxjava:1.2.2'compile'io.reactivex:rxandroid:1.2.1'注:雖然在我寫這篇文章的時(shí)候(2016.11.4)RxJava2.0剛剛release,但是我們還是先用RxJava1來寫這個(gè)demo.然后添加retrofit的adapter-rxjava:compile'com.squareup.retrofit2:adapter-rxjava:2.1.0'所以現(xiàn)在我們的依賴總的看起來是這樣:dependencies{compilefileTree(dir:'libs',include:['*.jar'])androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2',{excludegroup:'com.android.support',module:'support-annotations'})compile"com.android.support:appcompat-v7:${supportLibVersion}"compile"com.android.support:design:${supportLibVersion}"compile"com.jakewharton:butterknife:${butterKnifeVersion}"apt"com.jakewharton:butterknife-compiler:${butterKnifeVersion}"compile'com.squareup.retrofit2:retrofit:2.1.0'compile'com.google.code.gson:gson:2.8.0'compile'com.squareup.retrofit2:converter-gson:2.1.0'compile'com.squareup.retrofit2:adapter-rxjava:2.1.0'compile'io.reactivex:rxjava:1.2.2'compile'io.reactivex:rxandroid:1.2.1'testCompile'junit:junit:4.12'}Retrofit結(jié)合RxJavaRetrofit.Builder()中加入這一行:.addCallAdapterFactory(RxJavaCallAdapterFactory.create());ServiceGenerator變成這樣:publicclassServiceGenerator{publicstaticfinalStringAPI_BASE_URL="";privatestaticOkHttpClient.BuilderhttpClient=newOkHttpClient.Builder();privatestaticRetrofit.Builderbuilder=newRetrofit.Builder().baseUrl(API_BASE_URL).addConverterFactory(GsonConverterFactory.create()).addCallAdapterFactory(RxJavaCallAdapterFactory.create());publicstatic<S>ScreateService(Class<S>serviceClass){Retrofitretrofit=builder.client(httpClient.build()).build();returnretrofit.create(serviceClass);}}這樣我們?cè)贕ithubService中定義的接口方法,既可以像原來一樣返回Call,也可以返回Observable.Retrofit+RxJava請(qǐng)求實(shí)例以單個(gè)請(qǐng)求為例,不用RxJava的時(shí)候:@GET("users/{user}/following")Call<List<User>>getUserFollowing(@Path("user")Stringuser);請(qǐng)求的時(shí)候是這樣的:請(qǐng)求指定用戶follow的所有人:GitHubServiceservice=ServiceGenerator.createService(GitHubService.class);Call<List<User>>userFollowing=service.getUserFollowing(inputUserNameView.getText().toString());userFollowing.enqueue(newCallback<List<User>>(){@OverridepublicvoidonResponse(Call<List<User>>call,Response<List<User>>response){List<User>followingUsers=response.body();peopleListAdapter.setUsers(followingUsers);peopleListAdapter.notifyDataSetChanged();}@OverridepublicvoidonFailure(Call<List<User>>call,Throwablet){}});現(xiàn)在改用RxJava了,返回的不是Call而是Observable:@GET("users/{user}/following")Observable<List<User>>getUserFollowingObservable(@Path("user")Stringuser);結(jié)合RxJava請(qǐng)求的時(shí)候變?yōu)檫@樣:還是請(qǐng)求用戶follow的所有人:GitHubServiceservice=ServiceGenerator.createService(GitHubService.class);Stringusername=inputUserNameView.getText().toString();service.getUserFollowingObservable(username).subscribeO(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(newSubscriber<List<User>>(){@OverridepublicvoidonCompleted(){}@OverridepublicvoidonError(Throwablee){}@OverridepublicvoidonNext(List<User>users){LogUtils.i("onNext:"+users.size());peopleListAdapter.setUsers(users);peopleListAdapter.notifyDataSetChanged();}});用RxJava實(shí)現(xiàn)后,請(qǐng)求返回的是一個(gè)Observable,用subscribe()添加一個(gè)訂閱者,即它的觀察者.當(dāng)請(qǐng)求返回后,回到主線程,更新UI.這是單個(gè)請(qǐng)求的例子,所以RxJava的優(yōu)勢(shì)不是很明顯,如果我們有多個(gè)請(qǐng)求,用RxJava進(jìn)行變換組合顯然就是更好的選擇.用RxJava進(jìn)行線程切換上個(gè)例子中.subscribeOn(Schedulers.io())指定Observable的工作,在我們的例子中Observable的工作即發(fā)送請(qǐng)求,在io線程做,指定了被觀察者的處理線程;.observeOn(AndroidSchedulers.mainThread())指定最后onNext()回調(diào)在主線程,即指定了通知后續(xù)觀察者的線程.關(guān)于這兩個(gè)操作符的更多說明請(qǐng)看官方文檔:subscribeOn和observeOn.RxJava處理多個(gè)請(qǐng)求的例子設(shè)計(jì)這樣一個(gè)場(chǎng)景,我們現(xiàn)在取到了一個(gè)用戶follow的所有人,但是取回的信息中并不包含每個(gè)人擁有的repo個(gè)數(shù),只有一個(gè)url可用戶查看所有repo.接下來我們要取其中每一個(gè)人的詳細(xì)信息,就要查詢另一個(gè)API,重新查詢這個(gè)人的完整信息.查詢用戶follow的所有人,然后查詢每一個(gè)人的詳細(xì)信息:subscription=service.getUserFollowingObservable(username).flatMap(newFunc1<List<User>,Observable<User>>(){@OverridepublicObservable<User>call(List<User>users){returnObservable.from(users);}}).flatMap(newFunc1<User,Observable<User>>(){@OverridepublicObservable<User>call(Useruser){returnservice.getUserObservable(user.getLogin());}}).toList().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(newSubscriber<List<User>>(){@OverridepublicvoidonCompleted(){}@OverridepublicvoidonError(Throwablee){}@OverridepublicvoidonNext(List<User>users){peopleListAdapter.setUsers(users);peopleListAdapter.notifyDataSetChanged();}});可以看到我們加了兩個(gè)flatMap()和一個(gè)toList()來做這個(gè)事情.首先,第一步我們用getUserFollowingObservable()得到的是一個(gè)Observable<List<User>>;我們之后用.flatMap(),它的輸入是List<User>,返回的是Observable<User>.我們?cè)谄渲杏昧艘粋€(gè).from()來生成一個(gè)發(fā)射一組User的Observable;之后第二個(gè).flatMap()里,輸入是前一個(gè)Observable的輸出,即User,調(diào)用了getUserObservable(),返回的結(jié)果是Observable<User>,之后加一個(gè).toList(),把輸出的結(jié)果從單個(gè)的User變?yōu)長(zhǎng)ist,即和我們最初的例子一樣.只不過此時(shí)得到的用戶信息是更詳細(xì)的用戶信息,包含了他的repo數(shù)據(jù)和follow數(shù)據(jù).因?yàn)樗鼈兪峭ㄟ^單獨(dú)查詢每一個(gè)人得到的.運(yùn)行,雖然可以得到我們想要的結(jié)果,但是這個(gè)例子仍然是有問題的.線程問題處理上面多個(gè)請(qǐng)求的例子,發(fā)現(xiàn)雖然實(shí)現(xiàn)了我們的需求,但是結(jié)果回來得很慢.我們加上一個(gè).map操作符來加上log:(這里省略了一些前后的代碼,只是在.flatMap()里加了一個(gè).map())...subscription=service.getUserFollowingObservable(username).flatMap(newFunc1<List<User>,Observable<User>>(){@OverridepublicObservable<User>call(List<User>users){returnObservable.from(users);}}).flatMap(newFunc1<User,Observable<User>>(){@OverridepublicObservable<User>call(Useruser){returnservice.getUserObservable(user.getLogin()).map(newFunc1<User,User>(){@OverridepublicUsercall(Useruser){//this.mapisusedtooutputloginformationtocheckthethreadsLogUtils.i("getUserObservable:"+user.getLogin());returnuser;}});}}).toList()...由Log可以發(fā)現(xiàn)(log中的線程號(hào)是一樣的)單獨(dú)取每一個(gè)用戶詳細(xì)信息的請(qǐng)求都發(fā)生在同一個(gè)線程,是順次進(jìn)行的.查看代碼:Demo地址:/mengdd/HelloRetrofit.gitcheckoutmultiple-requests-in-single-thread回頭梳理一下我們的需求,請(qǐng)求一個(gè)所有follow的人,返回一個(gè)follow的人的List,然后對(duì)List中的每一個(gè)人,單獨(dú)請(qǐng)求詳細(xì)信息.那么按理來說,第二個(gè)批量的請(qǐng)求是可以同時(shí)發(fā)送,并行進(jìn)行的.所以我們想要的行為其實(shí)是平行發(fā)送多個(gè)請(qǐng)求,然后最后統(tǒng)一結(jié)果到UI線程.改動(dòng)如下:subscription=service.getUserFollowingObservable(username).subscribeOn(Schedulers.io())//從io線程開始,取用戶follow的所有人.flatMap(newFunc1<List<User>,Observable<User>>(){@OverridepublicObservable<User>call(List<User>users){LogUtils.i("from");returnObservable.from(users);}}).flatMap(newFunc1<User,Observable<User>>(){@OverridepublicObservable<User>call(Useruser){returnservice.getUserObservable(user.getLogin())//取每個(gè)人的詳細(xì)信息.subscribeOn(Schedulers.io())//指定取每個(gè)人詳細(xì)信息的工作都在單獨(dú)的io線程.map(newFunc1<User,User>(){@OverridepublicUsercall(Useruser){//thismapoperationisjustusedforshowinglogLogUtils.i("getUserObservable:"+user.getLogin());returnuser;}});}}).toList().observeOn(AndroidSchedulers.mainThread())//最后返回到主線程.subscribe(newSubscriber<List<User>>(){@OverridepublicvoidonCompleted(){}@OverridepublicvoidonError(Throwablee){}@OverridepublicvoidonNext(List<User>users){LogUtils.i("onNext:"+users.size());peopleListAdapter.setUsers(users);peopleListAdap
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年度酒店地毯翻新與采購(gòu)合同書3篇
- 物業(yè)管理公司課程設(shè)計(jì)
- 幼兒國(guó)旗下講話消防記我心講話稿(17篇)
- 2025年山東淄博市事業(yè)單位招聘工作人員124人歷年管理單位筆試遴選500模擬題附帶答案詳解
- 2025年山東濟(jì)寧汶上縣教育事業(yè)單位招聘301人歷年管理單位筆試遴選500模擬題附帶答案詳解
- 2025年山東濟(jì)南槐蔭區(qū)事業(yè)單位招考統(tǒng)計(jì)(9.13)及調(diào)管理單位筆試遴選500模擬題附帶答案詳解
- 2025年山東棗莊市郵政快遞安全中心招聘工作人員2人歷年管理單位筆試遴選500模擬題附帶答案詳解
- 房地產(chǎn)員工試用期的工作總結(jié)
- 把信送給加西亞讀后感(23篇)
- 小學(xué)心肺復(fù)蘇課程設(shè)計(jì)
- 【MOOC】英語科技文獻(xiàn)閱讀-哈爾濱工業(yè)大學(xué) 中國(guó)大學(xué)慕課MOOC答案
- 系統(tǒng)解剖學(xué)(南方醫(yī)科大學(xué))智慧樹知到期末考試答案章節(jié)答案2024年南方醫(yī)科大學(xué)
- 《生物質(zhì)熱電聯(lián)產(chǎn)工程設(shè)計(jì)規(guī)范》
- 科研倫理與學(xué)術(shù)規(guī)范期末考試
- GB/T 10000-2023中國(guó)成年人人體尺寸
- 湖南省住宅物業(yè)服務(wù)分項(xiàng)目分等級(jí)基準(zhǔn)價(jià)標(biāo)準(zhǔn)[完整版]
- 2024國(guó)家開放大學(xué)電大??啤秾W(xué)前兒童發(fā)展心理學(xué)》期末試題及答案
- 中國(guó) 黑龍江 哈爾濱日出日落時(shí)間表
- 2019年上海市春考高考英語試卷(精校含答案)
- (完整版)小學(xué)五年級(jí)英語上冊(cè)用所給詞語的適當(dāng)形式填空
- 刑法學(xué)形成性考核冊(cè)參考答案
評(píng)論
0/150
提交評(píng)論