优化换源

pull/341/head^2
gedoor 5 years ago
parent c4303af574
commit 1496927823
  1. 100
      app/src/main/java/io/legado/app/ui/book/changesource/ChangeSourceViewModel.kt

@ -10,30 +10,35 @@ import io.legado.app.base.BaseViewModel
import io.legado.app.constant.AppPattern import io.legado.app.constant.AppPattern
import io.legado.app.constant.PreferKey import io.legado.app.constant.PreferKey
import io.legado.app.data.entities.Book import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookSource
import io.legado.app.data.entities.SearchBook import io.legado.app.data.entities.SearchBook
import io.legado.app.help.AppConfig import io.legado.app.help.AppConfig
import io.legado.app.help.coroutine.Coroutine import io.legado.app.help.coroutine.CompositeCoroutine
import io.legado.app.model.WebBook import io.legado.app.model.WebBook
import io.legado.app.utils.getPrefBoolean import io.legado.app.utils.getPrefBoolean
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.ExecutorCoroutineDispatcher
import kotlinx.coroutines.asCoroutineDispatcher import kotlinx.coroutines.asCoroutineDispatcher
import org.jetbrains.anko.debug import org.jetbrains.anko.debug
import java.util.concurrent.CopyOnWriteArraySet
import java.util.concurrent.Executors import java.util.concurrent.Executors
class ChangeSourceViewModel(application: Application) : BaseViewModel(application) { class ChangeSourceViewModel(application: Application) : BaseViewModel(application) {
private var searchPool = val threadCount = AppConfig.threadCount
Executors.newFixedThreadPool(AppConfig.threadCount).asCoroutineDispatcher() private lateinit var searchPool: ExecutorCoroutineDispatcher
val handler = Handler() val handler = Handler()
val searchStateData = MutableLiveData<Boolean>() val searchStateData = MutableLiveData<Boolean>()
val searchBooksLiveData = MutableLiveData<List<SearchBook>>() val searchBooksLiveData = MutableLiveData<List<SearchBook>>()
var name: String = "" var name: String = ""
var author: String = "" var author: String = ""
private var task: Coroutine<*>? = null private var tasks = CompositeCoroutine()
private var screenKey: String = "" private var screenKey: String = ""
private val searchBooks = hashSetOf<SearchBook>() private var bookSourceList = arrayListOf<BookSource>()
private val searchBooks = CopyOnWriteArraySet<SearchBook>()
private var postTime = 0L private var postTime = 0L
private val sendRunnable = Runnable { upAdapter() } private val sendRunnable = Runnable { upAdapter() }
@Volatile
private var searchIndex = -1
fun initData(arguments: Bundle?) { fun initData(arguments: Bundle?) {
arguments?.let { bundle -> arguments?.let { bundle ->
@ -46,13 +51,17 @@ class ChangeSourceViewModel(application: Application) : BaseViewModel(applicatio
} }
} }
private fun initSearchPool() {
searchPool = Executors.newFixedThreadPool(threadCount).asCoroutineDispatcher()
}
fun loadDbSearchBook() { fun loadDbSearchBook() {
execute { execute {
App.db.searchBookDao().getByNameAuthorEnable(name, author).let { App.db.searchBookDao().getByNameAuthorEnable(name, author).let {
searchBooks.addAll(it) searchBooks.addAll(it)
if (it.size <= 1) { if (it.size <= 1) {
upAdapter() upAdapter()
search() startSearch()
} else { } else {
upAdapter() upAdapter()
} }
@ -83,38 +92,53 @@ class ChangeSourceViewModel(application: Application) : BaseViewModel(applicatio
upAdapter() upAdapter()
} }
fun search() { private fun startSearch() {
task = execute { execute {
val bookSourceList = App.db.bookSourceDao().allEnabled bookSourceList.clear()
for (item in bookSourceList) { bookSourceList.addAll(App.db.bookSourceDao().allEnabled)
//task取消时自动取消 by (scope = this@execute) searchStateData.postValue(true)
WebBook(item).searchBook(name, scope = this@execute, context = searchPool) initSearchPool()
.timeout(30000L) for (i in 0 until threadCount) {
.onSuccess(IO) { search()
it.forEach { searchBook -> }
if (searchBook.name == name && searchBook.author == author) { }
if (context.getPrefBoolean(PreferKey.changeSourceLoadToc)) { }
if (searchBook.tocUrl.isEmpty()) {
loadBookInfo(searchBook.toBook()) private fun search() {
} else { synchronized(this) {
loadChapter(searchBook.toBook()) searchIndex++
} val source = bookSourceList[searchIndex]
val task = WebBook(source).searchBook(name, scope = this, context = searchPool)
.timeout(60000L)
.onSuccess(IO) {
it.forEach { searchBook ->
if (searchBook.name == name && searchBook.author == author) {
if (context.getPrefBoolean(PreferKey.changeSourceLoadToc)) {
if (searchBook.tocUrl.isEmpty()) {
loadBookInfo(searchBook.toBook())
} else { } else {
searchFinish(searchBook) loadChapter(searchBook.toBook())
} }
return@onSuccess } else {
searchFinish(searchBook)
} }
return@forEach
} }
} }
} }
}.onStart { .onFinally {
searchStateData.postValue(true) synchronized(this) {
}.onCancel { if (searchIndex < bookSourceList.lastIndex) {
searchStateData.postValue(false) search()
} } else {
searchIndex++
task?.invokeOnCompletion { }
searchStateData.postValue(false) if (searchIndex >= bookSourceList.lastIndex + threadCount) {
searchStateData.postValue(false)
}
}
}
tasks.add(task)
} }
} }
@ -166,10 +190,12 @@ class ChangeSourceViewModel(application: Application) : BaseViewModel(applicatio
} }
fun stopSearch() { fun stopSearch() {
if (task?.isActive == true) { if (tasks.isEmpty) {
task?.cancel() startSearch()
} else { } else {
search() tasks.clear()
searchPool.close()
searchStateData.postValue(false)
} }
} }

Loading…
Cancel
Save