优化
This commit is contained in:
@@ -16,6 +16,7 @@ import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.CoroutineStart
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.sync.Semaphore
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
abstract class BaseService : LifecycleService() {
|
||||
@@ -28,8 +29,9 @@ abstract class BaseService : LifecycleService() {
|
||||
context: CoroutineContext = Dispatchers.IO,
|
||||
start: CoroutineStart = CoroutineStart.DEFAULT,
|
||||
executeContext: CoroutineContext = Dispatchers.Main,
|
||||
semaphore: Semaphore? = null,
|
||||
block: suspend CoroutineScope.() -> T
|
||||
) = Coroutine.async(scope, context, start, executeContext, block)
|
||||
) = Coroutine.async(scope, context, start, executeContext, semaphore, block)
|
||||
|
||||
@CallSuper
|
||||
override fun onCreate() {
|
||||
|
||||
@@ -10,6 +10,7 @@ import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.CoroutineStart
|
||||
import kotlinx.coroutines.Deferred
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.sync.Semaphore
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
@Suppress("unused")
|
||||
@@ -22,18 +23,22 @@ open class BaseViewModel(application: Application) : AndroidViewModel(applicatio
|
||||
context: CoroutineContext = Dispatchers.IO,
|
||||
start: CoroutineStart = CoroutineStart.DEFAULT,
|
||||
executeContext: CoroutineContext = Dispatchers.Main,
|
||||
semaphore: Semaphore? = null,
|
||||
block: suspend CoroutineScope.() -> T
|
||||
): Coroutine<T> {
|
||||
return Coroutine.async(scope, context, start, executeContext, block)
|
||||
return Coroutine.async(scope, context, start, executeContext, semaphore, block)
|
||||
}
|
||||
|
||||
fun <T> executeLazy(
|
||||
scope: CoroutineScope = viewModelScope,
|
||||
context: CoroutineContext = Dispatchers.IO,
|
||||
executeContext: CoroutineContext = Dispatchers.Main,
|
||||
semaphore: Semaphore? = null,
|
||||
block: suspend CoroutineScope.() -> T
|
||||
): Coroutine<T> {
|
||||
return Coroutine.async(scope, context, CoroutineStart.LAZY, executeContext, block)
|
||||
return Coroutine.async(
|
||||
scope, context, CoroutineStart.LAZY, executeContext, semaphore, block
|
||||
)
|
||||
}
|
||||
|
||||
fun <R> submit(
|
||||
|
||||
@@ -132,6 +132,9 @@ interface BookDao {
|
||||
@Query("select exists(select 1 from books where bookUrl = :bookUrl)")
|
||||
fun has(bookUrl: String): Boolean
|
||||
|
||||
@Query("select exists(select 1 from books where name = :name and author = :author)")
|
||||
fun has(name: String, author: String): Boolean
|
||||
|
||||
@Query(
|
||||
"""select exists(select 1 from books where type & ${BookType.local} > 0
|
||||
and (originName = :fileName or (origin != '${BookType.localTag}' and origin like '%' || :fileName)))"""
|
||||
|
||||
@@ -13,6 +13,7 @@ import kotlinx.coroutines.ensureActive
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.plus
|
||||
import kotlinx.coroutines.sync.Semaphore
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.coroutines.withTimeout
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
@@ -23,10 +24,11 @@ import kotlin.coroutines.CoroutineContext
|
||||
*/
|
||||
@Suppress("unused", "MemberVisibilityCanBePrivate")
|
||||
class Coroutine<T>(
|
||||
val scope: CoroutineScope,
|
||||
private val scope: CoroutineScope,
|
||||
context: CoroutineContext = Dispatchers.IO,
|
||||
val startOption: CoroutineStart = CoroutineStart.DEFAULT,
|
||||
val executeContext: CoroutineContext = Dispatchers.Main,
|
||||
private val startOption: CoroutineStart = CoroutineStart.DEFAULT,
|
||||
private val executeContext: CoroutineContext = Dispatchers.Main,
|
||||
private val semaphore: Semaphore? = null,
|
||||
block: suspend CoroutineScope.() -> T
|
||||
) {
|
||||
|
||||
@@ -39,9 +41,10 @@ class Coroutine<T>(
|
||||
context: CoroutineContext = Dispatchers.IO,
|
||||
start: CoroutineStart = CoroutineStart.DEFAULT,
|
||||
executeContext: CoroutineContext = Dispatchers.Main,
|
||||
semaphore: Semaphore? = null,
|
||||
block: suspend CoroutineScope.() -> T
|
||||
): Coroutine<T> {
|
||||
return Coroutine(scope, context, start, executeContext, block)
|
||||
return Coroutine(scope, context, start, executeContext, semaphore, block)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -169,6 +172,7 @@ class Coroutine<T>(
|
||||
block: suspend CoroutineScope.() -> T
|
||||
): Job {
|
||||
return (scope.plus(executeContext)).launch(start = startOption) {
|
||||
semaphore?.acquire()
|
||||
try {
|
||||
start?.let { dispatchVoidCallback(this, it) }
|
||||
ensureActive()
|
||||
@@ -185,7 +189,11 @@ class Coroutine<T>(
|
||||
error?.let { dispatchCallback(this, e, it) }
|
||||
}
|
||||
} finally {
|
||||
finally?.let { dispatchVoidCallback(this, it) }
|
||||
try {
|
||||
finally?.let { dispatchVoidCallback(this, it) }
|
||||
} finally {
|
||||
semaphore?.release()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ import kotlinx.coroutines.CoroutineStart
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.ensureActive
|
||||
import kotlinx.coroutines.sync.Semaphore
|
||||
import kotlinx.coroutines.sync.withPermit
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.coroutineContext
|
||||
|
||||
@@ -283,12 +282,14 @@ object WebBook {
|
||||
executeContext: CoroutineContext = Dispatchers.Main,
|
||||
semaphore: Semaphore? = null,
|
||||
): Coroutine<String> {
|
||||
return Coroutine.async(scope, context, start = start, executeContext = executeContext) {
|
||||
semaphore?.withPermit {
|
||||
getContentAwait(bookSource, book, bookChapter, nextChapterUrl, needSave)
|
||||
} ?: run {
|
||||
getContentAwait(bookSource, book, bookChapter, nextChapterUrl, needSave)
|
||||
}
|
||||
return Coroutine.async(
|
||||
scope,
|
||||
context,
|
||||
start = start,
|
||||
executeContext = executeContext,
|
||||
semaphore = semaphore
|
||||
) {
|
||||
getContentAwait(bookSource, book, bookChapter, nextChapterUrl, needSave)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,8 +361,9 @@ object WebBook {
|
||||
name: String,
|
||||
author: String,
|
||||
context: CoroutineContext = Dispatchers.IO,
|
||||
semaphore: Semaphore? = null,
|
||||
): Coroutine<Pair<Book, BookSource>> {
|
||||
return Coroutine.async(scope, context) {
|
||||
return Coroutine.async(scope, context, semaphore = semaphore) {
|
||||
for (s in bookSourceParts) {
|
||||
val source = s.getBookSource() ?: continue
|
||||
val book = preciseSearchAwait(source, name, author).getOrNull()
|
||||
|
||||
@@ -10,6 +10,7 @@ import io.legado.app.data.appDb
|
||||
import io.legado.app.data.entities.Book
|
||||
import io.legado.app.data.entities.BookSourcePart
|
||||
import io.legado.app.exception.NoStackTraceException
|
||||
import io.legado.app.help.config.AppConfig
|
||||
import io.legado.app.help.coroutine.Coroutine
|
||||
import io.legado.app.help.http.decompressed
|
||||
import io.legado.app.help.http.newCallResponseBody
|
||||
@@ -24,7 +25,8 @@ import io.legado.app.utils.isAbsUrl
|
||||
import io.legado.app.utils.isJsonArray
|
||||
import io.legado.app.utils.printOnDebug
|
||||
import io.legado.app.utils.toastOnUi
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.sync.Semaphore
|
||||
import kotlinx.coroutines.sync.withPermit
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.OutputStreamWriter
|
||||
@@ -154,21 +156,26 @@ class BookshelfViewModel(application: Application) : BaseViewModel(application)
|
||||
private fun importBookshelfByJson(json: String, groupId: Long) {
|
||||
execute {
|
||||
val bookSourceParts = appDb.bookSourceDao.allEnabledPart
|
||||
val semaphore = Semaphore(AppConfig.threadCount + 1)
|
||||
GSON.fromJsonArray<Map<String, String?>>(json).getOrThrow().forEach { bookInfo ->
|
||||
if (!isActive) return@execute
|
||||
val name = bookInfo["name"] ?: ""
|
||||
val author = bookInfo["author"] ?: ""
|
||||
if (name.isNotEmpty() && appDb.bookDao.getBook(name, author) == null) {
|
||||
WebBook.preciseSearch(this, bookSourceParts, name, author)
|
||||
.onSuccess {
|
||||
val book = it.first
|
||||
if (groupId > 0) {
|
||||
book.group = groupId
|
||||
}
|
||||
book.save()
|
||||
}.onError { e ->
|
||||
context.toastOnUi(e.localizedMessage)
|
||||
if (name.isEmpty() || appDb.bookDao.has(name, author)) {
|
||||
return@forEach
|
||||
}
|
||||
semaphore.withPermit {
|
||||
WebBook.preciseSearch(
|
||||
this, bookSourceParts, name, author,
|
||||
semaphore = semaphore
|
||||
).onSuccess {
|
||||
val book = it.first
|
||||
if (groupId > 0) {
|
||||
book.group = groupId
|
||||
}
|
||||
book.save()
|
||||
}.onError { e ->
|
||||
context.toastOnUi(e.localizedMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
}.onError {
|
||||
|
||||
Reference in New Issue
Block a user