[英]how to call a function every several millisecond using coroutine in kotlin
我想每 3 秒收到一次網絡請求,並在某些情況下停止它。 我正在使用Coroutine
進行網絡請求。我使用了postDelayed()
方法並且它工作正常。 但是我想在上一個請求的上一個響應完成后發出下一個請求。我使用了Coroutine
delay
方法,但是 UI 已經凍結並且我的應用程序仍然處於無限循環中。如何使用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
:
private fun init() {
mHandler = Handler()
}
private fun pullRequest() {
mRunnable = Runnable {
repeatRequest()
Log.e(TAG, "in run")
mHandler.postDelayed(
mRunnable,
3000
)
}
mHandler.postDelayed(
mRunnable,
3000
)
}
private fun cancelRequest() {
viewModel.cancelRequest(processId).observe(this, Observer {
if (it != null) {
processShareViewModel.setProcess(it.process)
mHandler.removeCallbacks(mRunnable)
mHandler.removeCallbacksAndMessages(null)
isPullRequest = false
if (findNavController().currentDestination?.id == R.id.requstBrokerFragment) {
val nextAction = RequstBrokerFragmentDirections.actionRequstBrokerFragmentToHomeFragment()
// nextAction.keyprocess = it.process
findNavController().navigate(nextAction)
}
}
Log.e(TAG, "response request borker: " + it.toString())
})
}
override fun onDestroy() {
super.onDestroy()
// Stop the periodic task
isPullRequest = false
mHandler.removeCallbacks(mRunnable)
mHandler.removeCallbacksAndMessages(null)
}
您的用戶界面凍結,因為您的while
循環不間斷地運行:
while (isPullRequest){
repeatRequest()
}
您在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()
對於那些不熟悉 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()
看看這個問題,它有一個自定義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)
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.