|
@@ -0,0 +1,63 @@
|
|
|
|
|
+package com.atmob.keyboard_android.ext
|
|
|
|
|
+
|
|
|
|
|
+import com.atmob.keyboard_android.model.base.BaseResp
|
|
|
|
|
+import kotlinx.coroutines.CoroutineDispatcher
|
|
|
|
|
+import kotlinx.coroutines.Dispatchers
|
|
|
|
|
+import kotlinx.coroutines.ExperimentalCoroutinesApi
|
|
|
|
|
+import kotlinx.coroutines.flow.Flow
|
|
|
|
|
+import kotlinx.coroutines.flow.catch
|
|
|
|
|
+import kotlinx.coroutines.flow.flow
|
|
|
|
|
+import kotlinx.coroutines.flow.flowOn
|
|
|
|
|
+import kotlinx.coroutines.suspendCancellableCoroutine
|
|
|
|
|
+import kotlin.coroutines.resumeWithException
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 回调异常
|
|
|
|
|
+ */
|
|
|
|
|
+class CallbackException(
|
|
|
|
|
+ val errorCode: Int,
|
|
|
|
|
+ val errorMsg: String
|
|
|
|
|
+) : Exception("errorCode=$errorCode, errorMsg=$errorMsg")
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 将传统的回调方式转换为Kotlin协程的可挂起函数
|
|
|
|
|
+ */
|
|
|
|
|
+@OptIn(ExperimentalCoroutinesApi::class)
|
|
|
|
|
+suspend inline fun <T> callback2Coroutines(
|
|
|
|
|
+ crossinline block: (onSuccess: (T) -> Unit, onFail: (Int, String) -> Unit) -> Unit
|
|
|
|
|
+): T = suspendCancellableCoroutine { continuation ->
|
|
|
|
|
+ block(
|
|
|
|
|
+ { result ->
|
|
|
|
|
+ continuation.resume(result) {
|
|
|
|
|
+ // 当协程在 resume 之后被取消时的处理
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ { code, msg ->
|
|
|
|
|
+ // 带取消回调的异常恢复
|
|
|
|
|
+ continuation.resumeWithException(
|
|
|
|
|
+ CallbackException(code, msg)
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ // 协程被取消时的操作
|
|
|
|
|
+ continuation.invokeOnCancellation {
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 协程转Flow
|
|
|
|
|
+ */
|
|
|
|
|
+fun <T> asFlow(
|
|
|
|
|
+ dispatcher: CoroutineDispatcher = Dispatchers.IO,
|
|
|
|
|
+ block: suspend () -> T
|
|
|
|
|
+): Flow<BaseResp<T>> = flow {
|
|
|
|
|
+ emit(BaseResp.success<T>(block()))
|
|
|
|
|
+}.catch { e ->
|
|
|
|
|
+ emit(
|
|
|
|
|
+ when (e) {
|
|
|
|
|
+ is CallbackException -> BaseResp.error(e.errorCode, e.errorMsg)
|
|
|
|
|
+ else -> BaseResp.error()
|
|
|
|
|
+ }
|
|
|
|
|
+ )
|
|
|
|
|
+}.flowOn(dispatcher)
|