pull/32/head
Administrator 5 years ago
parent cc7816949f
commit 189ed326dc
  1. 11
      app/src/main/java/io/legado/app/help/coroutine/CompositeCoroutine.kt
  2. 44
      app/src/main/java/io/legado/app/help/coroutine/Coroutine.kt
  3. 2
      app/src/main/java/io/legado/app/help/coroutine/CoroutineContainer.kt
  4. 4
      app/src/main/java/io/legado/app/ui/search/SearchActivity.kt
  5. 28
      app/src/main/java/io/legado/app/ui/search/SearchViewModel.kt
  6. 1
      app/src/main/res/layout/activity_search.xml

@ -1,5 +1,7 @@
package io.legado.app.help.coroutine package io.legado.app.help.coroutine
import android.util.Log
class CompositeCoroutine : CoroutineContainer { class CompositeCoroutine : CoroutineContainer {
private var resources: HashSet<Coroutine<*>>? = null private var resources: HashSet<Coroutine<*>>? = null
@ -76,10 +78,11 @@ class CompositeCoroutine : CoroutineContainer {
resources = null resources = null
} }
set?.forEach { Log.e("TAG", "size: ${set?.size}")
runCatching {
it.cancel() set?.forEachIndexed { index, coroutine ->
} Log.e("TAG", "index: $index")
coroutine.cancel()
} }
} }
} }

@ -44,8 +44,8 @@ class Coroutine<T>() {
scope: CoroutineScope, scope: CoroutineScope,
block: suspend CoroutineScope.() -> T block: suspend CoroutineScope.() -> T
) : this() { ) : this() {
this.job = scope.launch { this.job = scope.plus(Dispatchers.Main).launch {
executeInternal(block) executeInternal(this@launch, block)
} }
} }
@ -119,55 +119,51 @@ class Coroutine<T>() {
//取消当前任务 //取消当前任务
fun cancel(cause: CancellationException? = null) { fun cancel(cause: CancellationException? = null) {
job?.cancelChildren(cause)
job?.cancel(cause) job?.cancel(cause)
} }
private suspend fun executeInternal(block: suspend CoroutineScope.() -> T) { private suspend fun executeInternal(scope: CoroutineScope, block: suspend CoroutineScope.() -> T) {
tryCatch( tryCatch(
{ {
start?.invoke(this) start?.invoke(scope)
val result = executeBlockIO(block, timeMillis ?: 0L) val result = executeBlockIO(block, timeMillis ?: 0L)
success?.invoke(scope, result)
success?.invoke(this, result)
}, },
{ e -> { e ->
val consume: Boolean = errorReturn?.value?.let { value -> val consume: Boolean = errorReturn?.value?.let { value ->
success?.invoke(this, value) success?.invoke(scope, value)
true true
} ?: false } ?: false
if (!consume) { if (!consume) {
error?.invoke(this, e) error?.invoke(scope, e)
} }
}, },
{ {
finally?.invoke(this) finally?.invoke(scope)
}) })
} }
private suspend fun executeBlockIO(block: suspend CoroutineScope.() -> T, timeMillis: Long): T? { private suspend fun executeBlockIO(block: suspend CoroutineScope.() -> T, timeMillis: Long): T? {
val result: T = withContext(Dispatchers.IO) { val execution = withContext(Dispatchers.IO) {
val b = block() val result = block()
execute?.invoke(this, result)
execute?.invoke(this, b) result
b
} }
return if (timeMillis > 0L) withTimeout(timeMillis) { result } else result return if (timeMillis > 0L) withTimeout(timeMillis) { execution } else execution
} }
private suspend fun tryCatch( private suspend fun tryCatch(
tryBlock: suspend CoroutineScope.() -> Unit, tryBlock: suspend () -> Unit,
errorBlock: (suspend CoroutineScope.(Throwable) -> Unit)? = null, errorBlock: (suspend (Throwable) -> Unit)? = null,
finallyBlock: (suspend CoroutineScope.() -> Unit)? = null finallyBlock: (suspend () -> Unit)? = null
) { ) {
try { try {
coroutineScope { tryBlock() } tryBlock()
} catch (e: Throwable) { } catch (e: Throwable) {
coroutineScope { errorBlock?.invoke(this, e) } errorBlock?.invoke(e)
} finally { } finally {
coroutineScope { finallyBlock?.invoke(this) } finallyBlock?.invoke()
} }
} }

@ -1,6 +1,6 @@
package io.legado.app.help.coroutine package io.legado.app.help.coroutine
interface CoroutineContainer { internal interface CoroutineContainer {
fun add(coroutine: Coroutine<*>): Boolean fun add(coroutine: Coroutine<*>): Boolean

@ -11,6 +11,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import io.legado.app.App import io.legado.app.App
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.VMBaseActivity import io.legado.app.base.VMBaseActivity
import io.legado.app.data.entities.SearchBook
import io.legado.app.data.entities.SearchShow import io.legado.app.data.entities.SearchShow
import io.legado.app.lib.theme.ATH import io.legado.app.lib.theme.ATH
import io.legado.app.utils.getViewModel import io.legado.app.utils.getViewModel
@ -44,14 +45,13 @@ class SearchActivity : VMBaseActivity<SearchViewModel>(R.layout.activity_search)
viewModel.search(it, { startTime -> viewModel.search(it, { startTime ->
content_view.showContentView() content_view.showContentView()
initData(startTime) initData(startTime)
}, {
}) })
} }
return true return true
} }
override fun onQueryTextChange(newText: String?): Boolean { override fun onQueryTextChange(newText: String?): Boolean {
if(newText.isNullOrBlank()) viewModel.stop()
return false return false
} }

@ -3,7 +3,6 @@ package io.legado.app.ui.search
import android.app.Application import android.app.Application
import io.legado.app.App import io.legado.app.App
import io.legado.app.base.BaseViewModel import io.legado.app.base.BaseViewModel
import io.legado.app.help.coroutine.CompositeCoroutine
import io.legado.app.help.coroutine.Coroutine import io.legado.app.help.coroutine.Coroutine
import io.legado.app.model.WebBook import io.legado.app.model.WebBook
@ -12,18 +11,24 @@ class SearchViewModel(application: Application) : BaseViewModel(application) {
var searchPage = 0 var searchPage = 0
fun search(key: String, start: ((startTime: Long) -> Unit)? = null, finally: (() -> Unit)? = null) { fun search(
key: String,
start: ((startTime: Long) -> Unit)? = null,
finally: (() -> Unit)? = null
) {
if (key.isEmpty()) return if (key.isEmpty()) return
task?.cancel() task?.cancel()
start?.invoke(System.currentTimeMillis()) start?.invoke(System.currentTimeMillis())
task = execute {//onCleared时自动取消 task = execute {
//onCleared时自动取消
val bookSourceList = App.db.bookSourceDao().allEnabled val bookSourceList = App.db.bookSourceDao().allEnabled
for (item in bookSourceList) { for (item in bookSourceList) {
//task取消时自动取消 by (scope = this@execute) //task取消时自动取消 by (scope = this@execute)
WebBook(item).searchBook(key, searchPage, scope = this) WebBook(item).searchBook(key, searchPage, scope = this@execute)
.onExecute { searchBookS -> .timeout { 30000L }
searchBookS?.let { .onExecute {
App.db.searchBookDao().insert(*it.toTypedArray()) it?.let { list ->
App.db.searchBookDao().insert(*list.toTypedArray())
} }
} }
} }
@ -32,4 +37,13 @@ class SearchViewModel(application: Application) : BaseViewModel(application) {
it.printStackTrace() it.printStackTrace()
} }
} }
fun stop() {
task?.cancel()
}
override fun onCleared() {
super.onCleared()
task?.cancel()
}
} }

@ -11,6 +11,7 @@
android:id="@+id/title_bar" android:id="@+id/title_bar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:contentInsetStartWithNavigation="0dp"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:title="搜索"/> app:title="搜索"/>

Loading…
Cancel
Save