diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml index 105ce2da2..dd4c951ef 100644 --- a/.idea/inspectionProfiles/profiles_settings.xml +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -1,5 +1,6 @@ + diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md index 9ca52c3c0..6eed5099d 100644 --- a/app/src/main/assets/updateLog.md +++ b/app/src/main/assets/updateLog.md @@ -14,6 +14,7 @@ **2022/07/12** * 针对自建webDav进行优化,解决一些问题 by 821938089 +* 修复全文搜索新关键词时,老关键词搜索没有停止的bug **2022/07/10** diff --git a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentActivity.kt b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentActivity.kt index 13ff4324f..a44132933 100644 --- a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentActivity.kt @@ -7,6 +7,7 @@ import androidx.activity.viewModels import androidx.appcompat.widget.SearchView import io.legado.app.R import io.legado.app.base.VMBaseActivity +import io.legado.app.constant.AppLog import io.legado.app.constant.EventBus import io.legado.app.data.appDb import io.legado.app.data.entities.Book @@ -25,6 +26,8 @@ import io.legado.app.utils.observeEvent import io.legado.app.utils.postEvent import io.legado.app.utils.viewbindingdelegate.viewBinding import kotlinx.coroutines.Dispatchers.IO +import kotlinx.coroutines.Job +import kotlinx.coroutines.ensureActive import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -41,6 +44,7 @@ class SearchContentActivity : binding.titleBar.findViewById(R.id.search_view) } private var durChapterIndex = 0 + private var searchJob: Job? = null override fun onActivityCreated(savedInstanceState: Bundle?) { val bbg = bottomBackground @@ -133,35 +137,43 @@ class SearchContentActivity : fun startContentSearch(query: String) { // 按章节搜索内容 if (query.isNotBlank()) { + searchJob?.cancel() adapter.clearItems() viewModel.searchResultList.clear() viewModel.searchResultCounts = 0 viewModel.lastQuery = query - launch { - withContext(IO) { - appDb.bookChapterDao.getChapterList(viewModel.bookUrl) - }.forEach { bookChapter -> - binding.refreshProgressBar.isAutoLoading = true - val searchResults = withContext(IO) { - if (isLocalBook || viewModel.cacheChapterNames.contains(bookChapter.getFileName())) { - viewModel.searchChapter(query, bookChapter) - } else { - null + searchJob = launch { + kotlin.runCatching { + withContext(IO) { + appDb.bookChapterDao.getChapterList(viewModel.bookUrl) + }.forEach { bookChapter -> + ensureActive() + binding.refreshProgressBar.isAutoLoading = true + val searchResults = withContext(IO) { + if (isLocalBook || viewModel.cacheChapterNames.contains(bookChapter.getFileName())) { + viewModel.searchChapter(this, query, bookChapter) + } else { + null + } + } + binding.tvCurrentSearchInfo.text = + this@SearchContentActivity.getString(R.string.search_content_size) + ": ${viewModel.searchResultCounts}" + ensureActive() + if (searchResults != null && searchResults.isNotEmpty()) { + viewModel.searchResultList.addAll(searchResults) + binding.refreshProgressBar.isAutoLoading = false + adapter.addItems(searchResults) } } - binding.tvCurrentSearchInfo.text = - this@SearchContentActivity.getString(R.string.search_content_size) + ": ${viewModel.searchResultCounts}" - if (searchResults != null && searchResults.isNotEmpty()) { - viewModel.searchResultList.addAll(searchResults) - binding.refreshProgressBar.isAutoLoading = false - adapter.addItems(searchResults) + binding.refreshProgressBar.isAutoLoading = false + if (viewModel.searchResultCounts == 0) { + val noSearchResult = + SearchResult(resultText = getString(R.string.search_content_empty)) + adapter.addItem(noSearchResult) } - } - binding.refreshProgressBar.isAutoLoading = false - if (viewModel.searchResultCounts == 0) { - val noSearchResult = - SearchResult(resultText = getString(R.string.search_content_empty)) - adapter.addItem(noSearchResult) + }.onFailure { + binding.refreshProgressBar.isAutoLoading = false + AppLog.put("全文搜索出错\n${it.localizedMessage}", it) } } } diff --git a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentViewModel.kt b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentViewModel.kt index dd6914ddc..c529145ff 100644 --- a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentViewModel.kt @@ -10,7 +10,9 @@ import io.legado.app.data.entities.BookChapter import io.legado.app.help.BookHelp import io.legado.app.help.ContentProcessor import io.legado.app.help.config.AppConfig +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ensureActive import kotlinx.coroutines.withContext class SearchContentViewModel(application: Application) : BaseViewModel(application) { @@ -35,11 +37,16 @@ class SearchContentViewModel(application: Application) : BaseViewModel(applicati } } - suspend fun searchChapter(query: String, chapter: BookChapter?): List { + suspend fun searchChapter( + scope: CoroutineScope, + query: String, + chapter: BookChapter? + ): List { val searchResultsWithinChapter: MutableList = mutableListOf() if (chapter != null) { book?.let { book -> val chapterContent = BookHelp.getContent(book, chapter) + scope.ensureActive() if (chapterContent != null) { //先搜索没有启用净化的正文 withContext(Dispatchers.IO) { @@ -48,6 +55,7 @@ class SearchContentViewModel(application: Application) : BaseViewModel(applicati 2 -> ChineseUtils.s2t(chapter.title) else -> chapter.title } + scope.ensureActive() mContent = contentProcessor!!.getContent( book, chapter, chapterContent, chineseConvert = true, @@ -55,8 +63,9 @@ class SearchContentViewModel(application: Application) : BaseViewModel(applicati useReplace = false ).joinToString("") } - val positions = searchPosition(query) + val positions = searchPosition(scope, query) positions.forEachIndexed { index, position -> + scope.ensureActive() val construct = getResultAndQueryIndex(mContent, position, query) val result = SearchResult( resultCountWithinChapter = index, @@ -76,7 +85,7 @@ class SearchContentViewModel(application: Application) : BaseViewModel(applicati return searchResultsWithinChapter } - private suspend fun searchPosition(pattern: String): List { + private suspend fun searchPosition(scope: CoroutineScope, pattern: String): List { val position: MutableList = mutableListOf() var index = mContent.indexOf(pattern) if (index >= 0) { @@ -86,6 +95,7 @@ class SearchContentViewModel(application: Application) : BaseViewModel(applicati index = mContent.indexOf(pattern) } while (index >= 0) { + scope.ensureActive() position.add(index) index = mContent.indexOf(pattern, index + 1) }