kunfei 4 سال پیش
والد
کامیت
f5fab4eb06

+ 16 - 6
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<BookSource>()
     private var searchBooks = arrayListOf<SearchBook>()
+    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() {

+ 2 - 0
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 ->

+ 8 - 11
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<ActivityBookSearchBinding, SearchViewModel
     }
 
     private fun initData() {
+        launch {
+            viewModel.searchDataFlow
+                .collect {
+                    adapter.setItems(it)
+                    delay(1000)
+                }
+        }
         launch {
             appDb.bookSourceDao.flowGroupEnabled().collect {
                 groups.clear()
@@ -204,9 +211,6 @@ class SearchActivity : VMBaseActivity<ActivityBookSearchBinding, SearchViewModel
                 upGroupMenu()
             }
         }
-        viewModel.searchBookLiveData.observe(this) {
-            upSearchItems(it)
-        }
         viewModel.isSearchLiveData.observe(this) {
             if (it) {
                 startSearch()
@@ -310,13 +314,6 @@ class SearchActivity : VMBaseActivity<ActivityBookSearchBinding, SearchViewModel
         }
     }
 
-    /**
-     * 更新搜索结果
-     */
-    private fun upSearchItems(items: List<SearchBook>) {
-        adapter.setItems(items)
-    }
-
     /**
      * 开始搜索
      */

+ 36 - 47
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<Boolean>()
-    var searchBookLiveData = MutableLiveData<List<SearchBook>>()
     var searchKey: String = ""
     var isLoading = false
-    private var searchBooks = arrayListOf<SearchBook>()
     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) {
         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<SearchBook>) {
-        this.searchBooks = searchBooks
-        upAdapter()
-    }
-
-    override fun onSearchFinish() {
-        isSearchLiveData.postValue(false)
-        isLoading = false
-    }
-
-    override fun onSearchCancel() {
-        isSearchLiveData.postValue(false)
-        isLoading = false
-    }
-
-
     /**
      * 停止搜索
      */