Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/210.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 抽象协程结构_Android_Kotlin_Kotlin Coroutines - Fatal编程技术网

Android 抽象协程结构

Android 抽象协程结构,android,kotlin,kotlin-coroutines,Android,Kotlin,Kotlin Coroutines,使用RxJava我们可以执行以下操作: BaseViewModel protected void subscribe(Completable completable, MutableLiveData<Response> response) { mDisposable.add( completable.observeOn(AndroidSchedulers.mainThread()) .subscribeOn(Sc

使用
RxJava
我们可以执行以下操作:

BaseViewModel

protected void subscribe(Completable completable, MutableLiveData<Response> response) {
    mDisposable.add(
            completable.observeOn(AndroidSchedulers.mainThread())
                    .subscribeOn(Schedulers.io())
                    .doOnSubscribe(disposable -> response.setValue(Response.loading()))
                    .doFinally(() -> response.setValue(Response.idle()))
                    .subscribe(
                            () -> response.setValue(Response.success(true)),
                            e -> response.setValue(Response.error(e))
                    )
    );
}

protected <T> void subscribe(Single<T> single, MutableLiveData<Response> response) {
    mDisposable.add(
            single.observeOn(AndroidSchedulers.mainThread())
                    .subscribeOn(Schedulers.io())
                    .doOnSubscribe(disposable -> response.setValue(Response.loading()))
                    .doFinally(() -> response.setValue(Response.idle()))
                    .subscribe(
                            result -> response.setValue(Response.success(result)),
                            e -> response.setValue(Response.error(e))
                    )
    );
}
apiCx<YourModelClass> {
        request = yourApiCall()

        success { yourModelClass ->
            Log.d(TAG, "success")
        }

        error {
            Log.e(TAG, "error")
        }
    }
protectedvoid subscribe(Completable Completable,MutableLiveData响应){
mDisposable.add(
completable.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.doOnSubscribe(一次性->response.setValue(response.load())
.doFinally(()->response.setValue(response.idle())
.订阅(
()->response.setValue(response.success(true)),
e->response.setValue(response.error(e))
)
);
}
受保护的void subscribe(单个、可变的LiveData响应){
mDisposable.add(
single.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.doOnSubscribe(一次性->response.setValue(response.load())
.doFinally(()->response.setValue(response.idle())
.订阅(
结果->response.setValue(response.success(result)),
e->response.setValue(response.error(e))
)
);
}
然后,我们从存储库中获取
Single/Complete
,并将其传递给我们的自定义
subscribe()
,然后我们获得带有数据的通用
结果
(可选),这是处理异步请求的非常简单的方法


我们如何用相似的结构抽象
协同程序
,而不是在
ViewModel
中的每个方法中编写
Launch
,并手动尝试/捕获错误?

您可能正在寻找类似的东西

CoroutineWrapper

fun <T> ViewModel.apiCx(context: CoroutineContext = Dispatchers.Default, init: suspend CxWrapper<T>.() -> Unit) {
    val wrap = CxWrapper<T>(context)
    wrap.launch {
        try {
            init.invoke(wrap)
            callCx(wrap)
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
}

private fun <T> callCx(wrap: CxWrapper<T>) {
    val response: Response<T>? = wrap.request

    response?.let {
        if (it.isSuccessful) {
            wrap.success(it.body())
        } else {
            wrap.fail(Pair(it.code(), it.message()))
        }
    }
}

class CxWrapper<T>(override val coroutineContext: CoroutineContext) : CoroutineScope {

    var request: Response<T>? = null

    internal var success: (T?) -> Unit = {}
    internal var fail: (Pair<Int, String?>) -> Unit = {}

    fun success(onSuccess: (T?) -> Unit) {
        success = onSuccess
    }

    fun error(onError: (Pair<Int, String?>) -> Unit) {
        fail = onError
    }
}
fun ViewModel.apiCx(上下文:CoroutineContext=Dispatchers.Default,init:suspend CxWrapper.(->Unit){
val wrap=CxWrapper(上下文)
包装,发射{
试一试{
init.invoke(wrap)
callCx(包装)
}捕获(e:例外){
e、 printStackTrace()
}
}
}
专用趣味callCx(wrap:CxWrapper){
val响应:响应?=wrap.request
回答?让我说{
如果(it.ISSUCCESS){
wrap.success(it.body())
}否则{
wrap.fail(配对(it.code(),it.message())
}
}
}
类CxWrapper(重写val coroutineContext:coroutineContext):CoroutineScope{
var请求:响应?=null
内部变量成功:(T?->Unit={}
内部变量失败:(对)->Unit={}
趣味成功(成功时:(T?->单位){
成功=成功
}
有趣的错误(一个错误:(对)->单位){
失败=错误
}
}
您可以将其作为一个单独的帮助器类,并从您的视图模型中使用它

protected void subscribe(Completable completable, MutableLiveData<Response> response) {
    mDisposable.add(
            completable.observeOn(AndroidSchedulers.mainThread())
                    .subscribeOn(Schedulers.io())
                    .doOnSubscribe(disposable -> response.setValue(Response.loading()))
                    .doFinally(() -> response.setValue(Response.idle()))
                    .subscribe(
                            () -> response.setValue(Response.success(true)),
                            e -> response.setValue(Response.error(e))
                    )
    );
}

protected <T> void subscribe(Single<T> single, MutableLiveData<Response> response) {
    mDisposable.add(
            single.observeOn(AndroidSchedulers.mainThread())
                    .subscribeOn(Schedulers.io())
                    .doOnSubscribe(disposable -> response.setValue(Response.loading()))
                    .doFinally(() -> response.setValue(Response.idle()))
                    .subscribe(
                            result -> response.setValue(Response.success(result)),
                            e -> response.setValue(Response.error(e))
                    )
    );
}
apiCx<YourModelClass> {
        request = yourApiCall()

        success { yourModelClass ->
            Log.d(TAG, "success")
        }

        error {
            Log.e(TAG, "error")
        }
    }
apiCx{
request=yourApiCall()
成功{yourModelClass->
日志d(标记“成功”)
}
错误{
Log.e(标记“error”)
}
}

您也可以这样做,只是适应了协同程序。只需使用所需的暂停方法替换不同的流类型

protected inline fun <T> MutableLiveData<Response>.subscribe(single: suspend () -> T) {
    viewModelScope.launch {
        try {
            value = Response.loading()
            value = withContext(Dispatchers.IO) {
                Response.success(single())
            }
        } catch(e: Throwable) {
            value = Response.error(e)
        } finally {
            value = Response.idle()
        }
    }
protectedinlinefun MutableLiveData.subscribe(单个:suspend()->T){
viewModelScope.launch{
试一试{
value=Response.loading()
值=withContext(Dispatchers.IO){
Response.success(single())
}
}捕获(e:可丢弃){
值=响应。错误(e)
}最后{
value=Response.idle()
}
}
要使用它,只需使用livedata作为接收器进行调用

responseLiveData.subscribe<T> {
    singleFromRepo()
}
responseLiveData.subscribe<Unit> {
    completableFromRepo()
}
responseLiveData.subscribe{
singleFromRepo()
}
responseLiveData.subscribe{
completableFromRepo()
}

我建议您在迁移到协同程序时,不要紧跟您已有的代码,只进行最小的修改,而要全面检查您的设计

嵌入到协同程序中的一个重要原则是结构化并发。这不仅与协同程序的作用域和取消有关,还与以任何名称使用未来有关(无论是
CompletionStage
delivered
Task
Single
或任何其他名称).根据结构化并发,未来基本上等同于没有定义作用域的活动线程。您应该避免它们

相反,您应该在代码中清楚地划分出启动新并行工作的位置,这些工作包含在启动站点提供的单个顶级代码块中

到目前为止,这意味着您在Android框架的每个代码入口点都有一个
launch
块,这是由于面向回调的编程模型的性质造成的

但是,该块中的所有内容都应根据结构化并发进行编码。如果只需要进行一次网络调用,则代码完全是按顺序进行的:进行调用、获取响应、处理它。网络调用本身成为挂起函数,并随调用结果完成,不接受回调。所有来自阻塞调用世界的传统设计模式适用于此

请参阅此处,了解如何将协同程序与
LiveData
一起使用,它可能会帮助您将设计映射到面向协同程序的设计: