From f5fab4eb061ca3ee40435339c88e8dbeaf6ae300 Mon Sep 17 00:00:00 2001 From: kunfei Date: Mon, 21 Feb 2022 16:49:41 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../legado/app/model/webBook/SearchModel.kt | 22 +++-- .../book/changesource/ChangeSourceDialog.kt | 2 + .../app/ui/book/search/SearchActivity.kt | 19 ++--- .../app/ui/book/search/SearchViewModel.kt | 83 ++++++++----------- 4 files changed, 62 insertions(+), 64 deletions(-) diff --git a/app/src/main/java/io/legado/app/model/webBook/SearchModel.kt b/app/src/main/java/io/legado/app/model/webBook/SearchModel.kt index 97d897759..ee9d36dc1 100644 --- a/app/src/main/java/io/legado/app/model/webBook/SearchModel.kt +++ b/app/src/main/java/io/legado/app/model/webBook/SearchModel.kt @@ -17,7 +17,7 @@ import splitties.init.appCtx import java.util.concurrent.Executors import kotlin.math.min -class SearchModel(private val scope: CoroutineScope, private val callBack: CallBack) { +class SearchModel(private val scope: CoroutineScope) { val threadCount = AppConfig.threadCount private var searchPool: ExecutorCoroutineDispatcher? = null private var mSearchId = 0L @@ -26,10 +26,19 @@ class SearchModel(private val scope: CoroutineScope, private val callBack: CallB private var tasks = CompositeCoroutine() private var bookSourceList = arrayListOf() private var searchBooks = arrayListOf() + private var callBack: CallBack? = null @Volatile private var searchIndex = -1 + fun registerCallback(callBack: CallBack) { + this.callBack = callBack + } + + fun unRegisterCallback() { + this.callBack = null + } + private fun initSearchPool() { searchPool?.close() searchPool = Executors @@ -37,10 +46,10 @@ class SearchModel(private val scope: CoroutineScope, private val callBack: CallB } fun search(searchId: Long, key: String) { - callBack.onSearchStart() + callBack?.onSearchStart() if (searchId != mSearchId) { if (key.isEmpty()) { - callBack.onSearchCancel() + callBack?.onSearchCancel() return } else { this.searchKey = key @@ -53,6 +62,7 @@ class SearchModel(private val scope: CoroutineScope, private val callBack: CallB searchPage = 1 val searchGroup = appCtx.getPrefString("searchGroup") ?: "" bookSourceList.clear() + callBack?.onSearchSuccess(searchBooks) if (searchGroup.isBlank()) { bookSourceList.addAll(appDb.bookSourceDao.allEnabled) } else { @@ -103,7 +113,7 @@ class SearchModel(private val scope: CoroutineScope, private val callBack: CallB appDb.searchBookDao.insert(*items.toTypedArray()) val precision = appCtx.getPrefBoolean(PreferKey.precisionSearch) 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 + min(bookSourceList.size, threadCount) ) { - callBack.onSearchFinish() + callBack?.onSearchFinish() } } @@ -189,7 +199,7 @@ class SearchModel(private val scope: CoroutineScope, private val callBack: CallB fun cancelSearch() { close() - callBack.onSearchCancel() + callBack?.onSearchCancel() } fun close() { diff --git a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeSourceDialog.kt b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeSourceDialog.kt index e468bce50..0225344cd 100644 --- a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeSourceDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeSourceDialog.kt @@ -148,6 +148,8 @@ class ChangeSourceDialog() : BaseDialogFragment(R.layout.dialog_change_source), adapter.setItems(it) delay(1000) } + } + launch { appDb.bookSourceDao.flowGroupEnabled().collect { groups.clear() it.map { group -> diff --git a/app/src/main/java/io/legado/app/ui/book/search/SearchActivity.kt b/app/src/main/java/io/legado/app/ui/book/search/SearchActivity.kt index 72ab2d6b6..764d28483 100644 --- a/app/src/main/java/io/legado/app/ui/book/search/SearchActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/search/SearchActivity.kt @@ -19,7 +19,6 @@ import io.legado.app.constant.AppPattern import io.legado.app.constant.PreferKey import io.legado.app.data.appDb 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.databinding.ActivityBookSearchBinding import io.legado.app.lib.theme.* @@ -30,6 +29,7 @@ import io.legado.app.utils.* import io.legado.app.utils.viewbindingdelegate.viewBinding import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Job +import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -195,6 +195,13 @@ class SearchActivity : VMBaseActivity) { - adapter.setItems(items) - } - /** * 开始搜索 */ diff --git a/app/src/main/java/io/legado/app/ui/book/search/SearchViewModel.kt b/app/src/main/java/io/legado/app/ui/book/search/SearchViewModel.kt index 0c706734a..f7ac25720 100644 --- a/app/src/main/java/io/legado/app/ui/book/search/SearchViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/search/SearchViewModel.kt @@ -8,20 +8,47 @@ import io.legado.app.data.appDb import io.legado.app.data.entities.SearchBook import io.legado.app.data.entities.SearchKeyword import io.legado.app.model.webBook.SearchModel -import kotlinx.coroutines.Job -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.callbackFlow +import kotlinx.coroutines.flow.conflate -class SearchViewModel(application: Application) : BaseViewModel(application), SearchModel.CallBack { - private val searchModel = SearchModel(viewModelScope, this) - private var upAdapterJob: Job? = null +class SearchViewModel(application: Application) : BaseViewModel(application) { + private val searchModel = SearchModel(viewModelScope) var isSearchLiveData = MutableLiveData() - var searchBookLiveData = MutableLiveData>() var searchKey: String = "" var isLoading = false - private var searchBooks = arrayListOf() 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) { + 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) { if ((searchKey == key) || key.isNotEmpty()) { searchModel.cancelSearch() - searchBooks.clear() - searchBookLiveData.postValue(searchBooks) searchID = System.currentTimeMillis() searchKey = key } @@ -40,42 +65,6 @@ class SearchViewModel(application: Application) : BaseViewModel(application), Se 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) { - this.searchBooks = searchBooks - upAdapter() - } - - override fun onSearchFinish() { - isSearchLiveData.postValue(false) - isLoading = false - } - - override fun onSearchCancel() { - isSearchLiveData.postValue(false) - isLoading = false - } - - /** * 停止搜索 */