Use latest retrofit version to properly cancel requests
Fix cancelation requests
This commit is contained in:
parent
d469299f42
commit
a8f06f609b
@ -99,14 +99,14 @@ dependencies {
|
|||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
||||||
|
|
||||||
implementation "androidx.appcompat:appcompat:1.1.0-beta01"
|
implementation "androidx.appcompat:appcompat:1.1.0-rc01"
|
||||||
implementation "androidx.recyclerview:recyclerview:1.1.0-alpha06"
|
implementation "androidx.recyclerview:recyclerview:1.1.0-beta01"
|
||||||
|
|
||||||
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
|
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
|
||||||
kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
|
kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
|
||||||
|
|
||||||
// Network
|
// Network
|
||||||
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
|
implementation 'com.squareup.retrofit2:retrofit:2.6.0'
|
||||||
implementation 'com.squareup.retrofit2:converter-moshi:2.4.0'
|
implementation 'com.squareup.retrofit2:converter-moshi:2.4.0'
|
||||||
implementation 'com.squareup.okhttp3:okhttp:3.14.1'
|
implementation 'com.squareup.okhttp3:okhttp:3.14.1'
|
||||||
implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'
|
implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'
|
||||||
|
@ -19,54 +19,40 @@ package im.vector.matrix.android.internal.network
|
|||||||
import arrow.core.Try
|
import arrow.core.Try
|
||||||
import arrow.core.failure
|
import arrow.core.failure
|
||||||
import arrow.core.recoverWith
|
import arrow.core.recoverWith
|
||||||
import arrow.effects.IO
|
|
||||||
import arrow.effects.fix
|
|
||||||
import arrow.effects.instances.io.async.async
|
|
||||||
import arrow.integrations.retrofit.adapter.runAsync
|
|
||||||
import com.squareup.moshi.JsonDataException
|
import com.squareup.moshi.JsonDataException
|
||||||
import com.squareup.moshi.Moshi
|
import com.squareup.moshi.Moshi
|
||||||
import im.vector.matrix.android.api.failure.Failure
|
import im.vector.matrix.android.api.failure.Failure
|
||||||
import im.vector.matrix.android.api.failure.MatrixError
|
import im.vector.matrix.android.api.failure.MatrixError
|
||||||
import im.vector.matrix.android.internal.di.MoshiProvider
|
import im.vector.matrix.android.internal.di.MoshiProvider
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
|
||||||
import okhttp3.ResponseBody
|
import okhttp3.ResponseBody
|
||||||
import retrofit2.Call
|
import retrofit2.Call
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import kotlin.coroutines.resume
|
|
||||||
|
|
||||||
internal suspend inline fun <DATA> executeRequest(block: Request<DATA>.() -> Unit) = Request<DATA>().apply(block).execute()
|
internal suspend inline fun <DATA : Any> executeRequest(block: Request<DATA>.() -> Unit) = Request<DATA>().apply(block).execute()
|
||||||
|
|
||||||
internal class Request<DATA> {
|
internal class Request<DATA : Any> {
|
||||||
|
|
||||||
private val moshi: Moshi = MoshiProvider.providesMoshi()
|
private val moshi: Moshi = MoshiProvider.providesMoshi()
|
||||||
lateinit var apiCall: Call<DATA>
|
lateinit var apiCall: Call<DATA>
|
||||||
|
|
||||||
suspend fun execute(): Try<DATA> {
|
suspend fun execute(): Try<DATA> {
|
||||||
return suspendCancellableCoroutine { continuation ->
|
return Try {
|
||||||
continuation.invokeOnCancellation {
|
val response = apiCall.awaitResponse()
|
||||||
Timber.v("Request is canceled")
|
if (response.isSuccessful) {
|
||||||
apiCall.cancel()
|
response.body()
|
||||||
|
?: throw IllegalStateException("The request returned a null body")
|
||||||
|
} else {
|
||||||
|
throw manageFailure(response.errorBody(), response.code())
|
||||||
}
|
}
|
||||||
val result = Try {
|
}.recoverWith {
|
||||||
val response = apiCall.runAsync(IO.async()).fix().unsafeRunSync()
|
when (it) {
|
||||||
if (response.isSuccessful) {
|
is IOException -> Failure.NetworkConnection(it)
|
||||||
response.body()
|
is Failure.ServerError,
|
||||||
?: throw IllegalStateException("The request returned a null body")
|
is Failure.OtherServerError -> it
|
||||||
} else {
|
else -> Failure.Unknown(it)
|
||||||
throw manageFailure(response.errorBody(), response.code())
|
}.failure()
|
||||||
}
|
|
||||||
}.recoverWith {
|
|
||||||
when (it) {
|
|
||||||
is IOException -> Failure.NetworkConnection(it)
|
|
||||||
is Failure.ServerError,
|
|
||||||
is Failure.OtherServerError -> it
|
|
||||||
else -> Failure.Unknown(it)
|
|
||||||
}.failure()
|
|
||||||
}
|
|
||||||
continuation.resume(result)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun manageFailure(errorBody: ResponseBody?, httpCode: Int): Throwable {
|
private fun manageFailure(errorBody: ResponseBody?, httpCode: Int): Throwable {
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* * Copyright 2019 New Vector Ltd
|
||||||
|
* *
|
||||||
|
* * Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* * you may not use this file except in compliance with the License.
|
||||||
|
* * You may obtain a copy of the License at
|
||||||
|
* *
|
||||||
|
* * http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* *
|
||||||
|
* * Unless required by applicable law or agreed to in writing, software
|
||||||
|
* * distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* * See the License for the specific language governing permissions and
|
||||||
|
* * limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.matrix.android.internal.network
|
||||||
|
|
||||||
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
|
import retrofit2.*
|
||||||
|
import kotlin.coroutines.resume
|
||||||
|
import kotlin.coroutines.resumeWithException
|
||||||
|
|
||||||
|
suspend fun <T : Any> Call<T>.awaitResponse(): Response<T> {
|
||||||
|
return suspendCancellableCoroutine { continuation ->
|
||||||
|
continuation.invokeOnCancellation {
|
||||||
|
cancel()
|
||||||
|
}
|
||||||
|
enqueue(object : Callback<T> {
|
||||||
|
override fun onResponse(call: Call<T>, response: Response<T>) {
|
||||||
|
continuation.resume(response)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(call: Call<T>, t: Throwable) {
|
||||||
|
continuation.resumeWithException(t)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -18,7 +18,18 @@ package im.vector.riotx.core.platform
|
|||||||
|
|
||||||
import com.airbnb.mvrx.BaseMvRxViewModel
|
import com.airbnb.mvrx.BaseMvRxViewModel
|
||||||
import com.airbnb.mvrx.MvRxState
|
import com.airbnb.mvrx.MvRxState
|
||||||
|
import im.vector.matrix.android.api.util.CancelableBag
|
||||||
import im.vector.riotx.BuildConfig
|
import im.vector.riotx.BuildConfig
|
||||||
|
|
||||||
abstract class VectorViewModel<S : MvRxState>(initialState: S)
|
abstract class VectorViewModel<S : MvRxState>(initialState: S)
|
||||||
: BaseMvRxViewModel<S>(initialState, false)
|
: BaseMvRxViewModel<S>(initialState, false) {
|
||||||
|
|
||||||
|
protected val cancelableBag = CancelableBag()
|
||||||
|
|
||||||
|
override fun onCleared() {
|
||||||
|
super.onCleared()
|
||||||
|
cancelableBag.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -97,7 +97,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
|
|||||||
observeRoomSummary()
|
observeRoomSummary()
|
||||||
observeEventDisplayedActions()
|
observeEventDisplayedActions()
|
||||||
observeInvitationState()
|
observeInvitationState()
|
||||||
room.loadRoomMembersIfNeeded()
|
cancelableBag += room.loadRoomMembersIfNeeded()
|
||||||
timeline.start()
|
timeline.start()
|
||||||
setState { copy(timeline = this@RoomDetailViewModel.timeline) }
|
setState { copy(timeline = this@RoomDetailViewModel.timeline) }
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user