如何在baseViewModel上实现coroutine async/等待
我正在使用此结构与Coroutine一起使用Raterofit来点击我的应用程序中的API请求,但是在某些屏幕上,我发送多个请求,我只想在加载所有请求时显示数据,但是我无法使用此结构来执行此操作?
interface MyApi{
@GET(API_DATA)
suspend fun getDataA(): Response<BaseResponse<MyApiResponse>>
@GET(API_DATA)
suspend fun getDataB(): Response<BaseResponse<MyApiResponse>>
@GET(API_DATA)
suspend fun getDataC(): Response<BaseResponse<MyApiResponse>>
}
//
class MyApiCalls(private val myApi: MyApi) {
suspend fun getDataA() =
myApi.getDataA()
suspend fun getDataB() =
myApi.getDataB()
suspend fun getDataC() =
myApi.getDataC()
}
//
class MyRepository(
private val myApiCalls: MyApiCalls
) : BaseRepository() {
suspend fun getDataA() = myApiCalls.getDataA()
suspend fun getDataB() = myApiCalls.getDataB()
suspend fun getDataC() = myApiCalls.getDataC()
}
// //
class MyViewModel(
private val repository: MyRepository,
) : BaseViewModel(repository) {
val dataAStatus = SingleLiveEvent<Status>()
val dataBStatus = SingleLiveEvent<Status>()
val dataCStatus = SingleLiveEvent<Status>()
fun getDataA() {
performNetworkCall({
repository.getDataA()
}, dataAStatus )
}
fun getDataB() {
performNetworkCall({
repository.getDataB()
}, dataBStatus)
}
fun getDataC() {
performNetworkCall({
repository.getDataC()
}, dataCStatus)
}
}
//
abstract class BaseViewModel(private val repository: BaseRepository) : ViewModel() {
val showNetworkError = SingleLiveEvent<Boolean>()
val statusToken = SingleLiveEvent<Status>()
val logoutStatus = SingleLiveEvent<Status>()
val refreshTokenStatus = SingleLiveEvent<Status>()
fun <D> performNetworkCall(
apiCall: suspend () -> Response<D>,
status: SingleLiveEvent<Status>,
doOnSuccess: (responseData: D?) -> Unit = {},
doOnFailure: (() -> Any) = {}
) {
if (isNetworkConnected()) {
viewModelScope.launch {
withContext(Dispatchers.IO) {
try {
status.postValue(Status.Loading)
val response = apiCall.invoke()
when {
response.code() in 200..300 -> {
doOnSuccess(response.body())
status.postValue(Status.Success(response.body()))
}
else -> {
doOnFailure()
status.postValue(Status.Error(
errorCode = ERRORS.DEFAULT_ERROR,
message = repository.getString(R.string.default_error)
)
)
} catch (e: Exception) {
doOnFailure()
status.postValue(
Status.Error(
errorCode = ERRORS.DEFAULT_ERROR,
message = repository.getString(R.string.default_error)
)
)
}
}
}
} else
status.postValue(
Status.Error(
errorCode = ERRORS.NO_INTRERNET,
message = repository.getString(R.string.no_internet_connection)
)
)
}
}
我想使用AYSNC等待从GetDataa和GetDatab读取有关我的活动/片段的数据,如何使用该结构来实施该结构,并保持在其他API请求中使用单个请求的能力
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
要并行调用函数,您可以使用
async
构建器:在您当前的结构中,我认为在
withContext(dispatchers.io)在
> persionnetworkCall()方法,除非您要回调
doonsuccess
和doonfailure
在后台线程中调用。更新
尝试使用下一个调用来重复您当前的结构:
我使用
coroutinescope
函数,它是为工作的并行分解而设计的。当此范围中的任何儿童Coroutine失败时,此范围会失败,其余的孩子都被取消。To call functions in parallel you can use
async
builder:In your current structure, I don't think there is a need in calling
withContext(Dispatchers.IO)
inperformNetworkCall()
method, unless you want the callbacksdoOnSuccess
anddoOnFailure
to be called in background thread.UPDATE
Try to use next calls to reuse your current structure:
I used
coroutineScope
function, it is designed for parallel decomposition of work. When any child coroutine in this scope fails, this scope fails and all the rest of the children are cancelled.而不是
dataastatus
和databstatus
。您可以拥有一个单个实时数据,例如singleliveEvent&lt; pair&lt;状态,状态&gt;&gt;()
。这里
myapicalls.getDataa()
和myapicalls.getDatab()
应返回status
。然后在您的活动或片段中观察此实时数据(
datastatus
)。Instead of
dataAStatus
anddataBStatus
. You can have one single live data likeSingleLiveEvent<Pair<Status,Status>>()
.Here
myApiCalls.getDataA()
andmyApiCalls.getDataB()
should be returningstatus
.And then observe on this live data (
dataStatus
) in your activity or fragment.