前言
由于當前正在寫的項目集成了兩個網絡請求框架(Volley and Retrofit)對比之下也是選擇了Retrofit师脂。既然選擇那自然要讓自己以后開發(fā)更加省力(就是懶)今缚。于是我在Retrofit中加入了Rxjava搁廓,這也是當下蠻流行的一個請求框架。然后又利用了Kotlin的一些新特性肯尺,使網絡請求變得特別簡單啥供,代碼量特別少。
正文
導包
首先需要導入相關的包薄翅,包括Rxjava(我這里使用的是1.x的版本,如果你使用的是2.x的版本影響不大)氓奈、Retrofit翘魄。
//Rxjava
compile 'io.reactivex:rxandroid:1.2.0'
compile 'io.reactivex:rxjava:1.2.0'
//Retrofit
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
compile 'com.squareup.retrofit2:adapter-rxjava:2.3.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.8.0'
初始化Retrofit
retrofit = Retrofit.Builder()
.client(build.build())
.baseUrl("你的url")
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build().create(RetrofitUrl::class.java)
client
傳入的是一個OkhttpClient
,這里我們需要創(chuàng)建一個OkhttpClient
對象舀奶,這個可以用來加入一些攔截器暑竟、連接等待時間等,以下是我的client
:
val build = OkHttpClient.Builder().connectTimeout(15,TimeUnit.SECONDS)
.writeTimeout(15,TimeUnit.SECONDS)
.readTimeout(15,TimeUnit.SECONDS)
val logging = HttpLoggingInterceptor(HttpLoggingInterceptor.Logger {
Log.e("retrofit url",it)
})
logging.level = HttpLoggingInterceptor.Level.BODY
我這里只設置了連接、讀但荤、寫超時時間和一個攔截器罗岖,用于在用Retrofit
請求網絡的時候可以獲取到請求的信息。然后是baseUrl
這里是設置網絡請求的通用的地址腹躁,格式類似于http://ip:端口/后臺項目名/
桑包,需要以/
結尾。而后的addConverterFactory
和addCallAdapterFactory
是我們剛剛導入的包纺非,用于添加gson
和RxJava
支持哑了,其中如果解析的時候有要求時間格式,可自定義一個gson
傳入:
val gson = GsonBuilder().setDateFormat("yyyy-MM-dd hh:mm:ss").create()
如果不要求時間格式烧颖,GsonConverterFactory.create(此處可以不傳參數(shù))
弱左。然后就是RetrofitUrl
,這是一個接口炕淮,名字可以根據(jù)個人喜好進行定義拆火,其內放置請求的接口:
interface RetrofitUrl {
//方法名自定義
@GET("接口地址")
fun load():Observable<對應實體類>
@FormUrlEncoded
@Post("接口地址")
fun load():Observable<對應實體類>
//需要傳遞參數(shù),多個參數(shù)逗號隔開
@GET("接口地址")
fun load(@Query("參數(shù)名字") 參數(shù)名字(可自定義):參數(shù)類型):Observable<對應實體類>
@FormUrlEncoded
@Post("接口地址")
fun load(@Field("參數(shù)名字") 參數(shù)名字(可自定義):參數(shù)類型):Observable<對應實體類>
//示例
@GET("load")
fun load():Observable<NetOuter<Orgs>>
@GET("load")
fun load(@Query("id") id:Int):Observable<NetOuter<Orgs>>
}
以上就是初始化大概過程鳖悠,初始化我是放在了自定義的Application
中完成榜掌,使用時通過Application
獲取到Retrofit
优妙。
請求網絡
以上都做完了就可以開始請求網絡了乘综。
通過Application
獲取到Retrofit
后,我們就可以通過它去調用我們剛剛在接口中定義的方法套硼,因為配置了RxJava
卡辰,所以調用方法后會返回一個Observable
,這也是我們在接口中定義的返回類型邪意,如果沒有添加RxJava
九妈,返回類型為Call
。這樣子我們就可以按照RxJava
的習慣去寫了:
retrofit().load()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object :Subscriber<NetOuter<Orgs>>(){
override fun onCompleted() {
}
override fun onNext(t: NetOuter<Orgs>?) {
//可以在這里對獲取到的數(shù)據(jù)進行處理
}
override fun onError(e: Throwable?) {
//請求失敗
}
)
這樣子我們就完成了一個網絡請求雾鬼,這里就進行了線程調度的操作萌朱,具體看操作者的需求,也可以加入以下RxJava
的操作符策菜。
雖然這樣子可以進行網絡請求晶疼,可如果每次請求都要去寫線程調度又覺得太麻煩了,都是一樣的代碼又憨。這時候我們就用到了Kotlin
的一個特性翠霍,擴展函數(shù)。我們新建一個Kotlin File
文件蠢莺,在其中寫入我們修改了的代碼:
fun <T> runRx(observable: Observable<T>, subscriber: Subscriber<T>): Subscription =
observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(subscriber)
讓我們調調這個方法看看效果:
runRx(retrofit().load(),object : Subscriber<NetOuter<Orgs>>() {
override fun onCompleted() {}
override fun onNext(t: NetOuter<Orgs>?) {
//可以在這里對獲取到的數(shù)據(jù)進行處理
}
override fun onError(e: Throwable?) {
//請求失敗
}
)
通過這一層的封裝寒匙,省去了線程調度的代碼,在大量請求的時候躏将,可以省去不少代碼锄弱。但是考蕾,就這個程度,還是覺得要一直寫object : Subscriber...
会宪,這個也不想寫辕翰,懶嘛。怎么辦狈谊?只能繼續(xù)封裝喜命,這時候就想到了Kotlin
的另一個特性,高階函數(shù)河劝。Kotlin
允許把一個方法當做一個參數(shù)進行使用壁榕,使用時通過Lambda
的方式展示,一樣在我們剛剛寫runRx
那個文件:
fun <T> runRxLambda(observable: Observable<T>,next:(T)->Unit,error:(e: Throwable?)->Unit,completed:() -> Unit = { Log.e("completed","completed") }): Subscription{
runRx(observable, object : Subscriber<T>() {
override fun onCompleted() { completed }
override fun onNext(t: T) { next(t) }
override fun onError(e: Throwable?) { error(e) }
})
}
這里通過next:(T)->Unit
將方法當做一個參數(shù)赎瞎,其中next
為這個參數(shù)的參數(shù)名字牌里,冒號后面的括號里面為這個方法需要的參數(shù),多個參數(shù)逗號隔開务甥,Unit
是返回類型牡辽,Unit
相當于Java
中的void
。其中還看到了completed:() -> Unit = { Log.e("completed","completed") }
這里用到了Kotlin
的參數(shù)默認值敞临,通過=
號將右邊當做左邊方法的默認實現(xiàn)态辛,如果操作者沒有實現(xiàn)這個方法,就用這個默認操作挺尿。runRxLambda
的方法內也就是調用了我們剛剛寫的runRx
方法奏黑,然后將對應的方法傳入就可以了。接下來看看效果:
runRxLambda(retrofit().load(),{
//我們在這里的操作就相當于在onNext中的操作编矾,參數(shù)可以通過it獲取
},{
//這里就是onError的實現(xiàn)熟史,參數(shù)也可以通過it獲取
})
runRxLambda(retrofit().load(),{
//我們在這里的操作就相當于在onNext中的操作,參數(shù)可以通過it獲取
},{
//這里就是onError的實現(xiàn)窄俏,參數(shù)也可以通過it獲取
},{
//這里是onCompleted,不實現(xiàn)也可以
})
結尾
以上就是所有的內容了蹂匹,這里的一些實現(xiàn)方式不止用在這里,這篇文章也只是當做一個拋磚引玉凹蜈,其中可能也有很多操作不到位限寞,講的不到位的,希望噴的小聲點踪区。有什么更好的想法也希望可以私信留言昆烁。
源碼 ======> Github