pull/32/head
Administrator 5 years ago
parent 01a7bc7889
commit ed41f5a6dd
  1. 4
      app/src/main/java/io/legado/app/base/BaseViewModel.kt
  2. 55
      app/src/main/java/io/legado/app/help/coroutine/Coroutine.kt
  3. 6
      app/src/main/java/io/legado/app/model/WebBook.kt
  4. 36
      app/src/main/java/io/legado/app/ui/search/SearchViewModel.kt

@ -13,11 +13,11 @@ open class BaseViewModel(application: Application) : AndroidViewModel(applicatio
AnkoLogger { AnkoLogger {
fun <T> execute(block: suspend CoroutineScope.() -> T): Coroutine<T> { fun <T> execute(block: suspend CoroutineScope.() -> T): Coroutine<T> {
return Coroutine.launch(this) { block() } return Coroutine.async(this) { block() }
} }
fun <T> submit(block: suspend CoroutineScope.() -> Deferred<T>): Coroutine<T> { fun <T> submit(block: suspend CoroutineScope.() -> Deferred<T>): Coroutine<T> {
return Coroutine.launch(this) { block().await() } return Coroutine.async(this) { block().await() }
} }
fun <T> plus(coroutine: Coroutine<T>): Coroutine<T> { fun <T> plus(coroutine: Coroutine<T>): Coroutine<T> {

@ -2,35 +2,38 @@ package io.legado.app.help.coroutine
import kotlinx.coroutines.* import kotlinx.coroutines.*
class Coroutine<T>(private val scope: CoroutineScope, private val block: suspend CoroutineScope.() -> T) { class Coroutine<T>() {
companion object { companion object {
private val DEFAULT = MainScope() private val DEFAULT = MainScope()
fun <T> launch(scope: CoroutineScope = DEFAULT, block: suspend CoroutineScope.() -> T): Coroutine<T> { fun <T> async(scope: CoroutineScope = DEFAULT, block: suspend CoroutineScope.() -> T): Coroutine<T> {
return Coroutine(scope, block) return Coroutine(scope, block)
} }
fun <T> plus(coroutine: Coroutine<T>): Coroutine<T> { fun <T> plus(coroutine: Coroutine<T>): Coroutine<T> {
return Coroutine(coroutine.scope, coroutine.block) return Coroutine(coroutine)
.timeout{ coroutine.timeMillis?:0 }
.onErrorReturn { coroutine.errorReturn?.value }
.onStart { coroutine.start }
.onSuccess { coroutine.success }
.onError { coroutine.error }
.onFinally { coroutine.finally }
} }
} }
private val job: Job private var coroutine: Coroutine<T>? = null
private var job: Job? = null
init { private constructor(
job = scope.launch { scope: CoroutineScope? = null,
executeInternal(block) block: (suspend CoroutineScope.() -> T)? = null
) : this() {
this.job = scope?.launch {
block?.let { executeInternal(it) }
} }
} }
private constructor(coroutine: Coroutine<T>) : this() {
this.coroutine = coroutine
this.job = coroutine.job
}
private var start: (() -> Unit)? = null private var start: (() -> Unit)? = null
private var success: ((T?) -> Unit)? = null private var success: ((T?) -> Unit)? = null
private var error: ((Throwable) -> Unit)? = null private var error: ((Throwable) -> Unit)? = null
@ -42,38 +45,62 @@ class Coroutine<T>(private val scope: CoroutineScope, private val block: suspend
fun timeout(timeMillis: () -> Long): Coroutine<T> { fun timeout(timeMillis: () -> Long): Coroutine<T> {
if (this.coroutine != null) {
this.coroutine!!.timeMillis = timeMillis()
} else {
this.timeMillis = timeMillis() this.timeMillis = timeMillis()
}
return this@Coroutine return this@Coroutine
} }
fun onErrorReturn(value: () -> T?): Coroutine<T> { fun onErrorReturn(value: () -> T?): Coroutine<T> {
if (this.coroutine != null) {
this.coroutine!!.errorReturn = Result(value())
} else {
errorReturn = Result(value()) errorReturn = Result(value())
}
return this@Coroutine return this@Coroutine
} }
fun onStart(start: (() -> Unit)): Coroutine<T> { fun onStart(start: (() -> Unit)): Coroutine<T> {
if (this.coroutine != null) {
this.coroutine!!.start = start
} else {
this.start = start this.start = start
}
return this@Coroutine return this@Coroutine
} }
fun onSuccess(success: (T?) -> Unit): Coroutine<T> { fun onSuccess(success: (T?) -> Unit): Coroutine<T> {
if (this.coroutine != null) {
this.coroutine!!.success = success
} else {
this.success = success this.success = success
}
return this@Coroutine return this@Coroutine
} }
fun onError(error: (Throwable) -> Unit): Coroutine<T> { fun onError(error: (Throwable) -> Unit): Coroutine<T> {
if (this.coroutine != null) {
this.coroutine!!.error = error
} else {
this.error = error this.error = error
}
return this@Coroutine return this@Coroutine
} }
fun onFinally(finally: () -> Unit): Coroutine<T> { fun onFinally(finally: () -> Unit): Coroutine<T> {
if (this.coroutine != null) {
this.coroutine!!.finally = finally
} else {
this.finally = finally this.finally = finally
}
return this@Coroutine return this@Coroutine
} }
//取消当前任务 //取消当前任务
fun cancel(cause: CancellationException? = null) { fun cancel(cause: CancellationException? = null) {
job.cancel(cause) job?.cancel(cause)
} }
private suspend fun executeInternal(block: suspend CoroutineScope.() -> T) { private suspend fun executeInternal(block: suspend CoroutineScope.() -> T) {

@ -12,7 +12,7 @@ import io.legado.app.model.webbook.BookList
class WebBook(private val bookSource: BookSource) { class WebBook(private val bookSource: BookSource) {
fun searchBook(key: String, page: Int?): Coroutine<List<SearchBook>> { fun searchBook(key: String, page: Int?): Coroutine<List<SearchBook>> {
return Coroutine.launch { return Coroutine.async {
bookSource.getSearchRule().searchUrl?.let { searchUrl -> bookSource.getSearchRule().searchUrl?.let { searchUrl ->
val analyzeUrl = AnalyzeUrl(searchUrl) val analyzeUrl = AnalyzeUrl(searchUrl)
val response = when { val response = when {
@ -29,9 +29,9 @@ class WebBook(private val bookSource: BookSource) {
else -> HttpHelper.getApiService<IHttpGetApi>(analyzeUrl.baseUrl) else -> HttpHelper.getApiService<IHttpGetApi>(analyzeUrl.baseUrl)
.getMap(analyzeUrl.url, analyzeUrl.fieldMap, analyzeUrl.headerMap).await() .getMap(analyzeUrl.url, analyzeUrl.fieldMap, analyzeUrl.headerMap).await()
} }
return@launch BookList.analyzeBookList(response, bookSource, analyzeUrl) return@async BookList.analyzeBookList(response, bookSource, analyzeUrl)
} }
return@launch arrayListOf<SearchBook>() return@async arrayListOf<SearchBook>()
} }
} }

@ -12,26 +12,23 @@ import io.legado.app.help.coroutine.Coroutine
import io.legado.app.help.http.HttpHelper import io.legado.app.help.http.HttpHelper
import io.legado.app.model.WebBook import io.legado.app.model.WebBook
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
class SearchViewModel(application: Application) : BaseViewModel(application) { class SearchViewModel(application: Application) : BaseViewModel(application) {
val searchBooks: LiveData<List<SearchBook>> = MutableLiveData() val searchBooks: LiveData<List<SearchBook>> = MutableLiveData()
fun search(start: (() -> Unit)? = null, finally: (() -> Unit)? = null) { fun search(start: (() -> Unit)? = null, finally: (() -> Unit)? = null) {
execute { val c = execute {
val response: String = HttpHelper.getApiService<CommonHttpApi>( val response: String = HttpHelper.getApiService<CommonHttpApi>(
"http://www.baidu.com" "http://www.baidu.com"
).get("http://www.baidu.com").await() ).get("http://www.baidu.com").await()
delay(4000L) delay(2000L)
Log.e("TAG1", Thread.currentThread().name)
response response
} }
.timeout { 100L }
.onErrorReturn { "error return" }
.onStart { .onStart {
Log.e("TAG!", "start") Log.e("TAG!", "start")
start?.let { it() } start?.let { it() }
@ -49,7 +46,32 @@ class SearchViewModel(application: Application) : BaseViewModel(application) {
} }
} }
plus(WebBook(BookSource()).searchBook("keyword", 1)) val c2 = plus(c)
// .timeout { 100L }
// .onErrorReturn { "error return2" }
.onStart {
Log.e("TAG!", "start2")
start?.let { it() }
}
.onSuccess {
Log.e("TAG!", "success2: $it")
}
.onError {
Log.e("TAG!", "error2: $it")
}
.onFinally {
Log.e("TAG!", "finally2")
if (finally != null) {
finally()
}
}
launch {
delay(1500L)
c2.cancel()
}
} }
} }

Loading…
Cancel
Save