pull/36/head
kunfei 5 years ago
parent e9279fd103
commit 5c594ffbd5
  1. 15
      app/src/main/java/io/legado/app/base/BaseViewModel.kt
  2. 29
      app/src/main/java/io/legado/app/help/coroutine/Coroutine.kt
  3. 5
      app/src/main/java/io/legado/app/ui/book/search/SearchActivity.kt
  4. 12
      app/src/main/java/io/legado/app/ui/book/search/SearchViewModel.kt

@ -8,17 +8,26 @@ import io.legado.app.help.coroutine.Coroutine
import kotlinx.coroutines.*
import org.jetbrains.anko.AnkoLogger
import org.jetbrains.anko.toast
import kotlin.coroutines.CoroutineContext
open class BaseViewModel(application: Application) : AndroidViewModel(application), CoroutineScope by MainScope(),
open class BaseViewModel(application: Application) : AndroidViewModel(application),
CoroutineScope by MainScope(),
AnkoLogger {
val context: Context by lazy { this.getApplication<App>() }
fun <T> execute(scope: CoroutineScope = this, block: suspend CoroutineScope.() -> T): Coroutine<T> {
fun <T> execute(
scope: CoroutineScope = this,
context: CoroutineContext = scope.coroutineContext.plus(Dispatchers.IO),
block: suspend CoroutineScope.() -> T
): Coroutine<T> {
return Coroutine.async(scope) { block() }
}
fun <R> submit(scope: CoroutineScope = this, block: suspend CoroutineScope.() -> Deferred<R>): Coroutine<R> {
fun <R> submit(
scope: CoroutineScope = this,
block: suspend CoroutineScope.() -> Deferred<R>
): Coroutine<R> {
return Coroutine.async(scope) { block().await() }
}

@ -1,18 +1,25 @@
package io.legado.app.help.coroutine
import android.util.Log
import kotlinx.coroutines.*
import kotlin.coroutines.CoroutineContext
class Coroutine<T>(scope: CoroutineScope, block: suspend CoroutineScope.() -> T) {
class Coroutine<T>(
scope: CoroutineScope,
context: CoroutineContext = scope.coroutineContext.plus(Dispatchers.IO),
block: suspend CoroutineScope.() -> T
) {
companion object {
val DEFAULT = MainScope()
fun <T> async(scope: CoroutineScope = DEFAULT, block: suspend CoroutineScope.() -> T): Coroutine<T> {
return Coroutine(scope, block)
fun <T> async(
scope: CoroutineScope = DEFAULT,
context: CoroutineContext = scope.coroutineContext.plus(Dispatchers.IO),
block: suspend CoroutineScope.() -> T
): Coroutine<T> {
return Coroutine(scope, context, block)
}
}
@ -37,7 +44,7 @@ class Coroutine<T>(scope: CoroutineScope, block: suspend CoroutineScope.() -> T)
get() = job.isCompleted
init {
this.job = executeInternal(scope, block)
this.job = executeInternal(scope, context, block)
}
fun timeout(timeMillis: () -> Long): Coroutine<T> {
@ -101,11 +108,15 @@ class Coroutine<T>(scope: CoroutineScope, block: suspend CoroutineScope.() -> T)
return job.invokeOnCompletion(handler)
}
private fun executeInternal(scope: CoroutineScope, block: suspend CoroutineScope.() -> T): Job {
private fun executeInternal(
scope: CoroutineScope,
context: CoroutineContext,
block: suspend CoroutineScope.() -> T
): Job {
return scope.plus(Dispatchers.Main).launch {
try {
start?.let { dispatchVoidCallback(this, it) }
val value = executeBlock(scope, timeMillis ?: 0L, block)
val value = executeBlock(context, timeMillis ?: 0L, block)
success?.let { dispatchCallback(this, value, it) }
} catch (e: Throwable) {
val consume: Boolean = errorReturn?.value?.let { value ->
@ -147,11 +158,11 @@ class Coroutine<T>(scope: CoroutineScope, block: suspend CoroutineScope.() -> T)
}
private suspend inline fun executeBlock(
scope: CoroutineScope,
context: CoroutineContext,
timeMillis: Long,
noinline block: suspend CoroutineScope.() -> T
): T? {
return withContext(scope.coroutineContext.plus(Dispatchers.IO)) {
return withContext(context) {
if (timeMillis > 0L) withTimeout(timeMillis) {
block()
} else block()

@ -107,7 +107,10 @@ class SearchActivity : VMBaseActivity<SearchViewModel>(R.layout.activity_book_se
private fun initOtherView() {
tv_clear_history.onClick { viewModel.clearHistory() }
fb_stop.onClick { viewModel.stop() }
fb_stop.onClick {
viewModel.stop()
refresh_progress_bar.isAutoLoading = false
}
}
private fun initData() {

@ -8,9 +8,13 @@ import io.legado.app.data.entities.SearchKeyword
import io.legado.app.help.coroutine.Coroutine
import io.legado.app.model.WebBook
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import java.util.concurrent.Executors
class SearchViewModel(application: Application) : BaseViewModel(application) {
private var searchPool = Executors.newFixedThreadPool(99).asCoroutineDispatcher()
private var task: Coroutine<*>? = null
var searchKey: String = ""
var startTime: Long = 0
@ -26,7 +30,7 @@ class SearchViewModel(application: Application) : BaseViewModel(application) {
searchKey = key
startTime = System.currentTimeMillis()
start?.invoke()
task = execute {
task = execute(context = searchPool) {
//onCleared时自动取消
val bookSourceList = App.db.bookSourceDao().allEnabled
for (item in bookSourceList) {
@ -53,6 +57,7 @@ class SearchViewModel(application: Application) : BaseViewModel(application) {
}
fun stop() {
searchPool.cancel()
task?.cancel()
}
@ -77,4 +82,9 @@ class SearchViewModel(application: Application) : BaseViewModel(application) {
App.db.searchKeywordDao().deleteAll()
}
}
override fun onCleared() {
searchPool.close()
super.onCleared()
}
}

Loading…
Cancel
Save