优化
This commit is contained in:
@@ -17,7 +17,7 @@ import splitties.init.appCtx
|
|||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
class SearchModel(private val scope: CoroutineScope, private val callBack: CallBack) {
|
class SearchModel(private val scope: CoroutineScope) {
|
||||||
val threadCount = AppConfig.threadCount
|
val threadCount = AppConfig.threadCount
|
||||||
private var searchPool: ExecutorCoroutineDispatcher? = null
|
private var searchPool: ExecutorCoroutineDispatcher? = null
|
||||||
private var mSearchId = 0L
|
private var mSearchId = 0L
|
||||||
@@ -26,10 +26,19 @@ class SearchModel(private val scope: CoroutineScope, private val callBack: CallB
|
|||||||
private var tasks = CompositeCoroutine()
|
private var tasks = CompositeCoroutine()
|
||||||
private var bookSourceList = arrayListOf<BookSource>()
|
private var bookSourceList = arrayListOf<BookSource>()
|
||||||
private var searchBooks = arrayListOf<SearchBook>()
|
private var searchBooks = arrayListOf<SearchBook>()
|
||||||
|
private var callBack: CallBack? = null
|
||||||
|
|
||||||
@Volatile
|
@Volatile
|
||||||
private var searchIndex = -1
|
private var searchIndex = -1
|
||||||
|
|
||||||
|
fun registerCallback(callBack: CallBack) {
|
||||||
|
this.callBack = callBack
|
||||||
|
}
|
||||||
|
|
||||||
|
fun unRegisterCallback() {
|
||||||
|
this.callBack = null
|
||||||
|
}
|
||||||
|
|
||||||
private fun initSearchPool() {
|
private fun initSearchPool() {
|
||||||
searchPool?.close()
|
searchPool?.close()
|
||||||
searchPool = Executors
|
searchPool = Executors
|
||||||
@@ -37,10 +46,10 @@ class SearchModel(private val scope: CoroutineScope, private val callBack: CallB
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun search(searchId: Long, key: String) {
|
fun search(searchId: Long, key: String) {
|
||||||
callBack.onSearchStart()
|
callBack?.onSearchStart()
|
||||||
if (searchId != mSearchId) {
|
if (searchId != mSearchId) {
|
||||||
if (key.isEmpty()) {
|
if (key.isEmpty()) {
|
||||||
callBack.onSearchCancel()
|
callBack?.onSearchCancel()
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
this.searchKey = key
|
this.searchKey = key
|
||||||
@@ -53,6 +62,7 @@ class SearchModel(private val scope: CoroutineScope, private val callBack: CallB
|
|||||||
searchPage = 1
|
searchPage = 1
|
||||||
val searchGroup = appCtx.getPrefString("searchGroup") ?: ""
|
val searchGroup = appCtx.getPrefString("searchGroup") ?: ""
|
||||||
bookSourceList.clear()
|
bookSourceList.clear()
|
||||||
|
callBack?.onSearchSuccess(searchBooks)
|
||||||
if (searchGroup.isBlank()) {
|
if (searchGroup.isBlank()) {
|
||||||
bookSourceList.addAll(appDb.bookSourceDao.allEnabled)
|
bookSourceList.addAll(appDb.bookSourceDao.allEnabled)
|
||||||
} else {
|
} else {
|
||||||
@@ -103,7 +113,7 @@ class SearchModel(private val scope: CoroutineScope, private val callBack: CallB
|
|||||||
appDb.searchBookDao.insert(*items.toTypedArray())
|
appDb.searchBookDao.insert(*items.toTypedArray())
|
||||||
val precision = appCtx.getPrefBoolean(PreferKey.precisionSearch)
|
val precision = appCtx.getPrefBoolean(PreferKey.precisionSearch)
|
||||||
mergeItems(scope, items, precision)
|
mergeItems(scope, items, precision)
|
||||||
callBack.onSearchSuccess(searchBooks)
|
callBack?.onSearchSuccess(searchBooks)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,7 +127,7 @@ class SearchModel(private val scope: CoroutineScope, private val callBack: CallB
|
|||||||
if (searchIndex >= bookSourceList.lastIndex
|
if (searchIndex >= bookSourceList.lastIndex
|
||||||
+ min(bookSourceList.size, threadCount)
|
+ min(bookSourceList.size, threadCount)
|
||||||
) {
|
) {
|
||||||
callBack.onSearchFinish()
|
callBack?.onSearchFinish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,7 +199,7 @@ class SearchModel(private val scope: CoroutineScope, private val callBack: CallB
|
|||||||
|
|
||||||
fun cancelSearch() {
|
fun cancelSearch() {
|
||||||
close()
|
close()
|
||||||
callBack.onSearchCancel()
|
callBack?.onSearchCancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun close() {
|
fun close() {
|
||||||
|
|||||||
@@ -148,6 +148,8 @@ class ChangeSourceDialog() : BaseDialogFragment(R.layout.dialog_change_source),
|
|||||||
adapter.setItems(it)
|
adapter.setItems(it)
|
||||||
delay(1000)
|
delay(1000)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
launch {
|
||||||
appDb.bookSourceDao.flowGroupEnabled().collect {
|
appDb.bookSourceDao.flowGroupEnabled().collect {
|
||||||
groups.clear()
|
groups.clear()
|
||||||
it.map { group ->
|
it.map { group ->
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import io.legado.app.constant.AppPattern
|
|||||||
import io.legado.app.constant.PreferKey
|
import io.legado.app.constant.PreferKey
|
||||||
import io.legado.app.data.appDb
|
import io.legado.app.data.appDb
|
||||||
import io.legado.app.data.entities.Book
|
import io.legado.app.data.entities.Book
|
||||||
import io.legado.app.data.entities.SearchBook
|
|
||||||
import io.legado.app.data.entities.SearchKeyword
|
import io.legado.app.data.entities.SearchKeyword
|
||||||
import io.legado.app.databinding.ActivityBookSearchBinding
|
import io.legado.app.databinding.ActivityBookSearchBinding
|
||||||
import io.legado.app.lib.theme.*
|
import io.legado.app.lib.theme.*
|
||||||
@@ -30,6 +29,7 @@ import io.legado.app.utils.*
|
|||||||
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
||||||
import kotlinx.coroutines.Dispatchers.IO
|
import kotlinx.coroutines.Dispatchers.IO
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
@@ -195,6 +195,13 @@ class SearchActivity : VMBaseActivity<ActivityBookSearchBinding, SearchViewModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun initData() {
|
private fun initData() {
|
||||||
|
launch {
|
||||||
|
viewModel.searchDataFlow
|
||||||
|
.collect {
|
||||||
|
adapter.setItems(it)
|
||||||
|
delay(1000)
|
||||||
|
}
|
||||||
|
}
|
||||||
launch {
|
launch {
|
||||||
appDb.bookSourceDao.flowGroupEnabled().collect {
|
appDb.bookSourceDao.flowGroupEnabled().collect {
|
||||||
groups.clear()
|
groups.clear()
|
||||||
@@ -204,9 +211,6 @@ class SearchActivity : VMBaseActivity<ActivityBookSearchBinding, SearchViewModel
|
|||||||
upGroupMenu()
|
upGroupMenu()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
viewModel.searchBookLiveData.observe(this) {
|
|
||||||
upSearchItems(it)
|
|
||||||
}
|
|
||||||
viewModel.isSearchLiveData.observe(this) {
|
viewModel.isSearchLiveData.observe(this) {
|
||||||
if (it) {
|
if (it) {
|
||||||
startSearch()
|
startSearch()
|
||||||
@@ -310,13 +314,6 @@ class SearchActivity : VMBaseActivity<ActivityBookSearchBinding, SearchViewModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新搜索结果
|
|
||||||
*/
|
|
||||||
private fun upSearchItems(items: List<SearchBook>) {
|
|
||||||
adapter.setItems(items)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 开始搜索
|
* 开始搜索
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -8,20 +8,47 @@ import io.legado.app.data.appDb
|
|||||||
import io.legado.app.data.entities.SearchBook
|
import io.legado.app.data.entities.SearchBook
|
||||||
import io.legado.app.data.entities.SearchKeyword
|
import io.legado.app.data.entities.SearchKeyword
|
||||||
import io.legado.app.model.webBook.SearchModel
|
import io.legado.app.model.webBook.SearchModel
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.channels.awaitClose
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.flow.callbackFlow
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.flow.conflate
|
||||||
|
|
||||||
class SearchViewModel(application: Application) : BaseViewModel(application), SearchModel.CallBack {
|
class SearchViewModel(application: Application) : BaseViewModel(application) {
|
||||||
private val searchModel = SearchModel(viewModelScope, this)
|
private val searchModel = SearchModel(viewModelScope)
|
||||||
private var upAdapterJob: Job? = null
|
|
||||||
var isSearchLiveData = MutableLiveData<Boolean>()
|
var isSearchLiveData = MutableLiveData<Boolean>()
|
||||||
var searchBookLiveData = MutableLiveData<List<SearchBook>>()
|
|
||||||
var searchKey: String = ""
|
var searchKey: String = ""
|
||||||
var isLoading = false
|
var isLoading = false
|
||||||
private var searchBooks = arrayListOf<SearchBook>()
|
|
||||||
private var searchID = 0L
|
private var searchID = 0L
|
||||||
private var postTime = 0L
|
|
||||||
|
val searchDataFlow = callbackFlow {
|
||||||
|
|
||||||
|
val callback = object : SearchModel.CallBack {
|
||||||
|
override fun onSearchStart() {
|
||||||
|
isSearchLiveData.postValue(true)
|
||||||
|
isLoading = true
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
override fun onSearchSuccess(searchBooks: ArrayList<SearchBook>) {
|
||||||
|
trySend(ArrayList(searchBooks))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSearchFinish() {
|
||||||
|
isSearchLiveData.postValue(false)
|
||||||
|
isLoading = false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSearchCancel() {
|
||||||
|
isSearchLiveData.postValue(false)
|
||||||
|
isLoading = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
searchModel.registerCallback(callback)
|
||||||
|
|
||||||
|
awaitClose {
|
||||||
|
searchModel.unRegisterCallback()
|
||||||
|
}
|
||||||
|
}.conflate()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 开始搜索
|
* 开始搜索
|
||||||
@@ -29,8 +56,6 @@ class SearchViewModel(application: Application) : BaseViewModel(application), Se
|
|||||||
fun search(key: String) {
|
fun search(key: String) {
|
||||||
if ((searchKey == key) || key.isNotEmpty()) {
|
if ((searchKey == key) || key.isNotEmpty()) {
|
||||||
searchModel.cancelSearch()
|
searchModel.cancelSearch()
|
||||||
searchBooks.clear()
|
|
||||||
searchBookLiveData.postValue(searchBooks)
|
|
||||||
searchID = System.currentTimeMillis()
|
searchID = System.currentTimeMillis()
|
||||||
searchKey = key
|
searchKey = key
|
||||||
}
|
}
|
||||||
@@ -40,42 +65,6 @@ class SearchViewModel(application: Application) : BaseViewModel(application), Se
|
|||||||
searchModel.search(searchID, searchKey)
|
searchModel.search(searchID, searchKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
|
||||||
private fun upAdapter() {
|
|
||||||
upAdapterJob?.cancel()
|
|
||||||
if (System.currentTimeMillis() >= postTime + 1000) {
|
|
||||||
postTime = System.currentTimeMillis()
|
|
||||||
searchBookLiveData.postValue(searchBooks)
|
|
||||||
} else {
|
|
||||||
upAdapterJob = viewModelScope.launch {
|
|
||||||
delay(1000)
|
|
||||||
upAdapter()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSearchStart() {
|
|
||||||
isSearchLiveData.postValue(true)
|
|
||||||
isLoading = true
|
|
||||||
}
|
|
||||||
|
|
||||||
@Synchronized
|
|
||||||
override fun onSearchSuccess(searchBooks: ArrayList<SearchBook>) {
|
|
||||||
this.searchBooks = searchBooks
|
|
||||||
upAdapter()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSearchFinish() {
|
|
||||||
isSearchLiveData.postValue(false)
|
|
||||||
isLoading = false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSearchCancel() {
|
|
||||||
isSearchLiveData.postValue(false)
|
|
||||||
isLoading = false
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 停止搜索
|
* 停止搜索
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user