mar*_*yam 3 android coroutine kotlin
我想每 3 秒收到一次网络请求,并在某些情况下停止它。我正在用于Coroutine网络请求。我使用了postDelayed()方法并且它工作正常。但我想在上一个请求的上一个响应完成后发出下一个请求。我使用了但 UI 已冻结delay的方法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
}
Run Code Online (Sandbox Code Playgroud)
这是我的片段中的代码:
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()
}
}
Run Code Online (Sandbox Code Playgroud)
我的解决方案使用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)
}
Run Code Online (Sandbox Code Playgroud)
对于那些刚接触协程的人
在 Build.gradle 中添加协程
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2'
Run Code Online (Sandbox Code Playgroud)
添加重复作业
/**
* 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)
}
}
}
Run Code Online (Sandbox Code Playgroud)
开始:
Job myJob = startRepeatingJob(1000L)
Run Code Online (Sandbox Code Playgroud)
停止:
myJob .cancel()
Run Code Online (Sandbox Code Playgroud)
你的 UI 冻结了,因为你的while循环正在不间断地运行:
while (isPullRequest){
repeatRequest()
}
Run Code Online (Sandbox Code Playgroud)
您正在异步启动一个协程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()
Run Code Online (Sandbox Code Playgroud)