implementation "com.squareup.retrofit2:retrofit:2.6.0"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.1'
implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2'
/**
@author: Young <( ̄︶ ̄)>
Create: 2019-07-03
*/
abstract class CoroutinePresenter<V : BaseView> : BasePresenter(), CoroutineScope by MainScope() {
lateinit var view: V
fun onCreate(view: V) {
this.view = view
}
fun onDestroy() {
cancel()
}
/**
* 单个网络任务+后续耗时操作
*/
fun <T, R> startSimpleJobWithWork(call: Call<T>, andThen: (T) -> R, complete: (R) -> Unit) {
coroutineTry {
view.showLoading()
val result = withContext(Dispatchers.IO) {
val source = withContext(Dispatchers.Default) { call.createCallBack() }
withContext(Dispatchers.Default) { andThen(source) }
}
view.hideLoading()
complete(result)
}
}
/**
* 单个网络任务
*/
fun <T> startSimpleJob(call: Call<T>, response: (T) -> Unit) {
coroutineTry {
view.showLoading()
val result = withContext(Dispatchers.Default) { call.createCallBack() }
view.hideLoading()
response(result)
}
}
/**
* 单个网络任务
*/
fun <T> startSimpleJob(source: Deferred<T>, complete: (T) -> Unit) {
coroutineTry {
view.showLoading()
val result = source.await()
view.hideLoading()
complete(result)
}
}
/**
* 多个任务
*/
fun startMultiJob(vararg jobs: suspend () -> Unit) {
coroutineTry {
view.showLoading()
withContext(Dispatchers.IO) {
jobs.forEach {
it()
}
}
view.hideLoading()
}
}
private fun coroutineTry(job: suspend (CoroutineScope) -> Unit) {
launch {
try {
supervisorScope {
job(this)
}
} catch (e: Exception) {
val errorResult = when (e) {
is ErrorResult -> e
is ConnectException -> ErrorResult()
is HttpException -> {
when (e.code()) {
in 500 until Int.MAX_VALUE -> {
ErrorResult(e.code().toString(), "服务器内部异常")
}
in 400 until 500 -> {
ErrorResult(e.code().toString(), "请求异常")
}
else -> null
}
}
is ParseException -> ErrorResult(errorMsg = "数据异常")
else -> ErrorResult()
}
view.requestError(errorResult)
}
view.hideLoading()
}
}
suspend fun <T> Call<T>.createCallBack() = suspendCoroutine<T> {
this.enqueue(CoroutineCallback<T>(it))
}
}
class CoroutineCallback<T>(private val continuation: Continuation<T>) : Callback<T> {
override fun onFailure(call: Call<T>, throwable: Throwable) {
continuation.resumeWithException(throwable)
}
override fun onResponse(call: Call<T>, response: Response<T>) {
response?.let {
if (it.errorBody() != null) {
val string = it.errorBody()?.string()
string?.let { info ->
try {
continuation.resumeWithException(Gson().fromJson(info, ErrorResult::class.java))
} catch (e: Exception) {
continuation.resumeWithException(e)
}
}
} else {
it.body()?.let {
continuation.resume(it)
} ?: continuation.resumeWithException(ErrorResult(errorMsg = "数据异常"))
}
}
}
}
使用:
startSimpleJobWithWork(apiWithToken.getBrands(QueryHelper.signQuery(TreeMap())), {
//耗时操作
sortData(it)}) {
view.solveData(it)
}
startSimpleJob(apiWithToken.getBrands(QueryHelper.signQuery(TreeMap()))){
view.vehicleBrandResponse(it)
}
@GET("/api/v0/xxxxxx")
fun getBrands(@QueryMap map1: MutableMap<String, Any>): Call<CarListResult>
或者
@GET("/api/v0/xxxxxx")
fun getBrands(@QueryMap map1: MutableMap<String, Any>): Deferred<CarListResult>
使用第二种方式暂时不知道怎样处理后端返回的自定义异常,有大神知道怎么操作请留言赐教。
网友评论