tags: Android
I haven’t written an article for two years, and I don’t know what to say for a while...beep...
I believe that everyone here can say a lot about the network request framework. However, what I am going to talk about today is not the network request framework. Today I will talk about the coroutine that is touted by everyone. And the difference from RxJava that everyone has abandoned, and whether RxJava can be as convenient and fast as a coroutine.
This article is based on Retrofit 2.9.0, and the request method is slightly different from the previous version, please note.
The first step is the configuration of Retrofit
object RetrofitManager {
fun <K> create(clazz: Class<K>) : K = getRetrofit().create(clazz)
private fun getRetrofit(): Retrofit {
// Get an instance of retrofit
return Retrofit.Builder()
//url must end with ‘/’, or IllegalArgumentException will be reported
.baseUrl(ApiService.BASE_URL)
.client(getOkHttpClient())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build()
}
private fun getOkHttpClient(): OkHttpClient {
//Add a log interceptor and print all logs
val httpLoggingInterceptor = HttpLoggingInterceptor()
//You can set the level of request filtering, body, basic, headers
httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
return OkHttpClient.Builder()
.addInterceptor(httpLoggingInterceptor) //Log, see all request responsiveness
.connectTimeout(15L, TimeUnit.SECONDS)
.readTimeout(15L, TimeUnit.SECONDS)
.writeTimeout(15L, TimeUnit.SECONDS)
.proxy(Proxy.NO_PROXY)
.build()
}
}
The source of the interface used in this demonstration andPlay android
interface ApiService {
companion object{
const val BASE_URL = "https://www.wanandroid.com/"
}
@GET("article/list/{page}/json")
fun getList(
@Path("page") page: Int
) : Observable<HomeListBean>
@GET("banner/json")
fun getBannerList(): Call<BannerBean>
@POST("postxxx/xxx")
fun postMsg(@Body json : RequestBody) : Observable<BaseBean>
}
Okay, let's review the network request made by traditional RxJava+Retrofit.
First encapsulate RxJava, although it may be different from your package, but it is also similar.
fun <T : Basexxx> request(){
check: Boolean = true,
function: Function<Boolean, ObservableSource<T>>,
next: Consumer<T>,
error: Consumer<Throwable> = Consumer {
finishRefreshorLoadData = true
errorLiveData.postValue(it)
}
) {
val disposable = Observable.just(check)
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.filter { t -> t }
.flatMap(function)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(next, error)
addSubscription(disposable)
}
Then the request might look like this
request(
function = Function<Boolean, ObservableSource<xxxBen>>{
//Network request
model.getList(1)
},
next = Consumer{
liveDataVideo.postValue(it)
}
)
Before I knew about the coroutine, it didn't seem to be a problem at first glance, but it was not simple enough.
Look at the network request of the coroutine:
GlobalScope.launch {
val bean = model.getBannerList().await()
liveData.postValue(bean)
}
Suck (inhale sharply).
Because Retrofit is version 2.9, the coroutine is directly encapsulated in Retrofit. As a developer, we don’t need to go to too much encapsulation and can directly call it.
Comparing the two, it is clear which one is better. Since the coroutine can be so simple, can RxJava?
Definitely.
First, let's analyze the part of the network request we care about:
1. Directly process the successful result of the request
2. Don't care about request exceptions
3. Interface destruction cancels the existing request
The final seal is as follows, implemented by the extension function
fun <T : BaseBean> Observable<T>.onResult(
next : (T) -> Unit
){
this onResult Consumer {
//Here is the return judgment, and the background agreement
if (!TextUtils.equals(it.errorCode,"200")){
errorLiveData.value = it.errorMsg
return@Consumer
}
next(it)
}
}
Look at the final use result
fun getList(){
//RxJava
model.getList(0).onResult {
liveData2.value = it
}
}
fun getBannerList(){
//Coroutine
GlobalScope.launch {
val bean = model.getBannerList().await()
liveData.postValue(bean)
}
}
Well, this is perfect.
Although the coroutine has unique features that can replace RxJava in network requests, the streaming programming of RxJava is not what coroutine can replace, and it is difficult to define which is better. I don’t know what you like.
Attach the RxJava package code at the end
open class BaseViewModel : ViewModel(),IViewModel {
val errorLiveData: MutableLiveData<String> = MutableLiveData()
private var compositeDisposable = CompositeDisposable()
override fun onCreate(owner: LifecycleOwner) {
//create
}
override fun onDestroy(owner: LifecycleOwner) {
//destroy
detachView()
//Remove the life cycle monitor observer
owner.lifecycle.removeObserver(this)
}
override fun onLifecycleChanged(owner: LifecycleOwner, event: Lifecycle.Event) {
//Life cycle status change
}
//Generic can be <T: BaseBean> or <T: List<BaseBean>>
//Here is the extended function of Observable, you can also change to the extended function of Flowable
fun <T : BaseBean> Observable<T>.onResult(
next: Consumer<T>,
error: Consumer<Throwable> = Consumer {
errorLiveData.postValue(it.message)
}
) {
val disposable = this.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(next, error)
addSubscription(disposable)
}
private infix fun <T : BaseBean> Observable<T>.onResult(
next: Consumer<T>
) {
this.onResult(next,Consumer {
errorLiveData.postValue(it.message)
})
}
fun <T : BaseBean> Observable<T>.onResult(
next : (T) -> Unit
){
this onResult Consumer {
//Return judgment here
/*if (!TextUtils.equals(it.errorCode,"200")){
errorLiveData.value = it.errorMsg
return@Consumer
}*/
next(it)
}
}
private fun addSubscription(disposable: Disposable) {
compositeDisposable.add(disposable)
}
private fun detachView() {
//Ensure that all ongoing subscriptions are cancelled when the activity ends
if (!compositeDisposable.isDisposed) {
compositeDisposable.clear()
}
}
}
Due to space limitations, this article only talks about the RxJava package, and the detailed code will not be posted. The demo address is attached. If you are interested, you can check it out.
github: https://github.com/cithrf/RxDemo
Why is it code refinement, not detailed or what, because there is really a lot of things involved, it is really a very laborious thing to talk about bit by bit. I believe that it is natural to learn t...
I. Background Often see items with Retrofit + RxJava + RxAndroid frame, in order to understand the structure of the project. Now take a look, Retrofit: Retrofit Square is a framework developed by a ne...
Retrofit binding request for network RxJava And using Refrogit2.0 RxJava2.0 used in combination, is simple to request the network to complete A first introducing dependencies: Second, add network perm...
1. Construct a retrofit instance and perform configuration customization, such as callAdapterFactory, convertFactory, and baseUrl; 2. Retrofit calls create to create a dynamic generation key is to cre...
The Android network request framework must be used in Android development. Personally used network request frameworks include Android-async-http, Volley, Okhttp, and Retrofit introduced in this articl...
1. Preliminary basic knowledge reserve In the previous four articles, the author has separately explained the usage of RxJava and the usage of Retrofit. The former implements asynchronous operation, a...
Depend on authority and take a walk~~~~~~~ Network request tools Connected service Specific request data interface...
brief introduction Retrofit is currently a very widely used network request framework. It is usually combined with RxJava to make network requests. This article will show a network request demo using ...
Import dependencies Retrofit interface Integrate rxjava and retrofit...