我想每3秒收到一次网络请求,并在某种情况下将其停止。我使用Coroutine
进行网络请求。我使用了postDelayed()
方法,它可以正常工作。但是我想在上一个请求的上一个响应完成后发出下一个请求。我使用了delay
的{{1}}方法,但是UI冻结了,我的应用仍处于无限循环中。使用Coroutine
或协程处理此任务?我在此存储库中创建网络请求:
postDelayed
这是我片段中的代码:
class ProcessRepository @Inject constructor(private val apiService: ApiService) {
val _networkState = MutableLiveData<NetworkState>()
val _networkState_first = MutableLiveData<NetworkState>()
val completableJob = Job()
private val coroutineScope = CoroutineScope(Dispatchers.IO + completableJob)
private val brokerProcessResponse = MutableLiveData<BrokerProcessResponse>()
fun repeatRequest(processId:String):MutableLiveData<BrokerProcessResponse>{
var networkState = NetworkState(Status.LOADING, userMessage)
_networkState.postValue(networkState)
coroutineScope.launch {
val request = apiService.repeatRequest(processId, token)
withContext(Dispatchers.Main) {
try {
val response = request.await()
if (response.isSuccessful) {
brokerProcessResponse.postValue(response.body())
var networkState = NetworkState(Status.SUCCESS, userMessage)
_networkState.postValue(networkState)
} else {
var networkState = NetworkState(Status.ERROR, userMessage)
_networkState.postValue(networkState)
}
} catch (e: IOException) {
var networkState = NetworkState(Status.ERROR, userMessage)
_networkState.postValue(networkState)
} catch (e: Throwable) {
var networkState = NetworkState(Status.ERROR, userMessage)
_networkState.postValue(networkState)
}
}
delay(3000) // I only just add this line for try solution using coroutine
}
return brokerProcessResponse
}
我的解决方案使用 private fun repeatRequest(){
viewModel.repeatRequest(processId).observe(this, Observer {
if(it!=null){
process=it.process
if(it.process.state== FINDING_BROKER || it.process.state==NONE){
inProgress(true)
}else{
inProgress(false)
}
setState(it!!.process.state!!,it.process)
}
})
}
private fun pullRequest(){
while (isPullRequest){
repeatRequest()
}
}
:
postDelayed
答案 0 :(得分:2)
您的UI死机了,因为您的while
循环没有中断:
while (isPullRequest){
repeatRequest()
}
您正在repeatRequest
中异步启动协程并在那里调用delay
。这不会暂停pullRequest
函数。
您应该在协程中运行循环(repeatRequest
函数)。然后,您可以将此协程的job
对象提供给调用方,并在需要停止循环时调用cancel
:
fun repeatRequest(): Job {
return coroutineScope.launch {
while(isActive) {
//do your request
delay(3000)
}
}
}
//start the loop
val repeatJob = repeatRequest()
//Cancel the loop
repeatJob.cancel()
答案 1 :(得分:2)
对于 Coroutine 的新手
在 Build.gradle 中添加 Coroutine
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2'
添加重复作业
/**
* start Job
* val job = startRepeatingJob()
* cancels the job and waits for its completion
* job.cancelAndJoin()
* Params
* timeInterval: time milliSeconds
*/
private fun startRepeatingJob(timeInterval: Long): Job {
return CoroutineScope(Dispatchers.Default).launch {
while (NonCancellable.isActive) {
// add your task here
doSomething()
delay(timeInterval)
}
}
}
开始:
Job myJob = startRepeatingJob(1000L)
停止:
myJob .cancel()
答案 2 :(得分:1)
看看这个question,它有一个自定义的loop
,用法看起来像这样
// if loop block takes less than 3 seconds, then this loop will iterate after every 3 seconds
// if loop block takes more than 3 seconds, then this loop will iterate after block is finished
// loop iterate after block duration or provided minimum interval whichever is maximum
loop(3.seconds) {
// make request
// process response
stopIf(condition)
}