diff --git a/app/src/main/java/io/legado/app/data/dao/HttpTTSDao.kt b/app/src/main/java/io/legado/app/data/dao/HttpTTSDao.kt index f97c17af1..934fcbfbb 100644 --- a/app/src/main/java/io/legado/app/data/dao/HttpTTSDao.kt +++ b/app/src/main/java/io/legado/app/data/dao/HttpTTSDao.kt @@ -1,8 +1,8 @@ package io.legado.app.data.dao -import androidx.lifecycle.LiveData import androidx.room.* import io.legado.app.data.entities.HttpTTS +import kotlinx.coroutines.flow.Flow @Dao interface HttpTTSDao { @@ -11,7 +11,7 @@ interface HttpTTSDao { val all: List @Query("select * from httpTTS order by name") - fun observeAll(): LiveData> + fun observeAll(): Flow> @get:Query("select count(*) from httpTTS") val count: Int diff --git a/app/src/main/java/io/legado/app/data/dao/ReplaceRuleDao.kt b/app/src/main/java/io/legado/app/data/dao/ReplaceRuleDao.kt index 2a0e1149c..f18a362a0 100644 --- a/app/src/main/java/io/legado/app/data/dao/ReplaceRuleDao.kt +++ b/app/src/main/java/io/legado/app/data/dao/ReplaceRuleDao.kt @@ -1,21 +1,24 @@ package io.legado.app.data.dao -import androidx.lifecycle.LiveData import androidx.room.* import io.legado.app.data.entities.ReplaceRule +import kotlinx.coroutines.flow.Flow @Dao interface ReplaceRuleDao { @Query("SELECT * FROM replace_rules ORDER BY sortOrder ASC") - fun liveDataAll(): LiveData> + fun liveDataAll(): Flow> @Query("SELECT * FROM replace_rules where `group` like :key or name like :key ORDER BY sortOrder ASC") - fun liveDataSearch(key: String): LiveData> + fun liveDataSearch(key: String): Flow> @Query("SELECT * FROM replace_rules where `group` like :key ORDER BY sortOrder ASC") - fun liveDataGroupSearch(key: String): LiveData> + fun liveDataGroupSearch(key: String): Flow> + + @Query("select `group` from replace_rules where `group` is not null and `group` <> ''") + fun liveGroup(): Flow> @get:Query("SELECT MIN(sortOrder) FROM replace_rules") val minOrder: Int @@ -44,9 +47,6 @@ interface ReplaceRuleDao { ) fun findEnabledByScope(name: String, origin: String): List - @Query("select `group` from replace_rules where `group` is not null and `group` <> ''") - fun liveGroup(): LiveData> - @Query("select * from replace_rules where `group` like '%' || :group || '%'") fun getByGroup(group: String): List diff --git a/app/src/main/java/io/legado/app/data/dao/RuleSubDao.kt b/app/src/main/java/io/legado/app/data/dao/RuleSubDao.kt index d5aea29ad..e6ab06827 100644 --- a/app/src/main/java/io/legado/app/data/dao/RuleSubDao.kt +++ b/app/src/main/java/io/legado/app/data/dao/RuleSubDao.kt @@ -1,8 +1,8 @@ package io.legado.app.data.dao -import androidx.lifecycle.LiveData import androidx.room.* import io.legado.app.data.entities.RuleSub +import kotlinx.coroutines.flow.Flow @Dao interface RuleSubDao { @@ -11,7 +11,7 @@ interface RuleSubDao { val all: List @Query("select * from ruleSubs order by customOrder") - fun observeAll(): LiveData> + fun observeAll(): Flow> @get:Query("select customOrder from ruleSubs order by customOrder limit 0,1") val maxOrder: Int diff --git a/app/src/main/java/io/legado/app/data/dao/SearchKeywordDao.kt b/app/src/main/java/io/legado/app/data/dao/SearchKeywordDao.kt index d3063759a..699432939 100644 --- a/app/src/main/java/io/legado/app/data/dao/SearchKeywordDao.kt +++ b/app/src/main/java/io/legado/app/data/dao/SearchKeywordDao.kt @@ -1,8 +1,8 @@ package io.legado.app.data.dao -import androidx.lifecycle.LiveData import androidx.room.* import io.legado.app.data.entities.SearchKeyword +import kotlinx.coroutines.flow.Flow @Dao @@ -12,13 +12,13 @@ interface SearchKeywordDao { val all: List @Query("SELECT * FROM search_keywords ORDER BY usage DESC") - fun liveDataByUsage(): LiveData> + fun liveDataByUsage(): Flow> @Query("SELECT * FROM search_keywords ORDER BY lastUseTime DESC") - fun liveDataByTime(): LiveData> + fun liveDataByTime(): Flow> @Query("SELECT * FROM search_keywords where word like '%'||:key||'%' ORDER BY usage DESC") - fun liveDataSearch(key: String): LiveData> + fun liveDataSearch(key: String): Flow> @Query("select * from search_keywords where word = :key") fun get(key: String): SearchKeyword? diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/SpeakEngineDialog.kt b/app/src/main/java/io/legado/app/ui/book/read/config/SpeakEngineDialog.kt index 233eef978..a6d7e06d9 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/config/SpeakEngineDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/config/SpeakEngineDialog.kt @@ -9,7 +9,7 @@ import android.view.View import android.view.ViewGroup import androidx.appcompat.widget.Toolbar import androidx.fragment.app.viewModels -import androidx.lifecycle.LiveData +import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.LinearLayoutManager import io.legado.app.R import io.legado.app.base.BaseDialogFragment @@ -31,6 +31,8 @@ import io.legado.app.ui.document.FilePickerParam import io.legado.app.ui.widget.dialog.TextDialog import io.legado.app.utils.* import io.legado.app.utils.viewbindingdelegate.viewBinding +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.launch import splitties.init.appCtx @@ -39,7 +41,6 @@ class SpeakEngineDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener private val ttsUrlKey = "ttsUrlKey" lateinit var adapter: Adapter private val viewModel: SpeakEngineViewModel by viewModels() - private var httpTTSData: LiveData>? = null private var engineId = appCtx.getPrefLong(PreferKey.speakEngine) private val importDocResult = registerForActivityResult(FilePicker()) { it?.let { @@ -103,11 +104,11 @@ class SpeakEngineDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener } private fun initData() { - httpTTSData?.removeObservers(this) - httpTTSData = appDb.httpTTSDao.observeAll() - httpTTSData?.observe(this, { - adapter.setItems(it) - }) + lifecycleScope.launch { + appDb.httpTTSDao.observeAll().collect { + adapter.setItems(it) + } + } } override fun onMenuItemClick(item: MenuItem?): Boolean { 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 afed9c5ab..90f202441 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 @@ -10,7 +10,6 @@ import android.view.View.VISIBLE import android.widget.TextView import androidx.activity.viewModels import androidx.appcompat.widget.SearchView -import androidx.lifecycle.LiveData import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView @@ -49,7 +48,7 @@ class SearchActivity : VMBaseActivity>? = null + private var historyFlowJob: Job? = null private var booksFlowJob: Job? = null private var menu: Menu? = null private var precisionSearchMenuItem: MenuItem? = null @@ -292,22 +291,20 @@ class SearchActivity : VMBaseActivity appDb.searchKeywordDao.liveDataByUsage() + else -> appDb.searchKeywordDao.liveDataSearch(key) + }.collect { + historyKeyAdapter.setItems(it) + if (it.isEmpty()) { + binding.tvClearHistory.invisible() + } else { + binding.tvClearHistory.visible() + } } - }) + } } /** diff --git a/app/src/main/java/io/legado/app/ui/replace/GroupManageDialog.kt b/app/src/main/java/io/legado/app/ui/replace/GroupManageDialog.kt index 24bac89bb..64c04a6d7 100644 --- a/app/src/main/java/io/legado/app/ui/replace/GroupManageDialog.kt +++ b/app/src/main/java/io/legado/app/ui/replace/GroupManageDialog.kt @@ -10,6 +10,7 @@ import android.view.ViewGroup import androidx.appcompat.widget.Toolbar import androidx.fragment.app.DialogFragment import androidx.fragment.app.activityViewModels +import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.LinearLayoutManager import io.legado.app.R import io.legado.app.base.adapter.ItemViewHolder @@ -25,6 +26,8 @@ import io.legado.app.lib.theme.primaryColor import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.utils.* import io.legado.app.utils.viewbindingdelegate.viewBinding +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.launch class GroupManageDialog : DialogFragment(), Toolbar.OnMenuItemClickListener { @@ -50,10 +53,11 @@ class GroupManageDialog : DialogFragment(), Toolbar.OnMenuItemClickListener { super.onViewCreated(view, savedInstanceState) view.setBackgroundColor(backgroundColor) binding.toolBar.setBackgroundColor(primaryColor) + initView() initData() } - private fun initData() = binding.run { + private fun initView() = binding.run { toolBar.title = getString(R.string.group_manage) toolBar.inflateMenu(R.menu.group_manage) toolBar.menu.applyTint(requireContext()) @@ -62,13 +66,18 @@ class GroupManageDialog : DialogFragment(), Toolbar.OnMenuItemClickListener { recyclerView.layoutManager = LinearLayoutManager(requireContext()) recyclerView.addItemDecoration(VerticalDivider(requireContext())) recyclerView.adapter = adapter - appDb.replaceRuleDao.liveGroup().observe(viewLifecycleOwner, { - val groups = linkedSetOf() - it.map { group -> - groups.addAll(group.splitNotBlank(AppPattern.splitGroupRegex)) + } + + private fun initData() { + lifecycleScope.launch { + appDb.replaceRuleDao.liveGroup().collect { + val groups = linkedSetOf() + it.map { group -> + groups.addAll(group.splitNotBlank(AppPattern.splitGroupRegex)) + } + adapter.setItems(groups.toList()) } - adapter.setItems(groups.toList()) - }) + } } override fun onMenuItemClick(item: MenuItem?): Boolean { diff --git a/app/src/main/java/io/legado/app/ui/replace/ReplaceRuleActivity.kt b/app/src/main/java/io/legado/app/ui/replace/ReplaceRuleActivity.kt index 56ff1257e..a2204038f 100644 --- a/app/src/main/java/io/legado/app/ui/replace/ReplaceRuleActivity.kt +++ b/app/src/main/java/io/legado/app/ui/replace/ReplaceRuleActivity.kt @@ -11,7 +11,7 @@ import androidx.activity.viewModels import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.SearchView import androidx.documentfile.provider.DocumentFile -import androidx.lifecycle.LiveData +import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.LinearLayoutManager import io.legado.app.R @@ -39,6 +39,9 @@ import io.legado.app.ui.widget.recycler.ItemTouchCallback import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.utils.* import io.legado.app.utils.viewbindingdelegate.viewBinding +import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.launch import java.io.File /** @@ -56,7 +59,7 @@ class ReplaceRuleActivity : VMBaseActivity() private var groupMenu: SubMenu? = null - private var replaceRuleLiveData: LiveData>? = null + private var replaceRuleFlowJob: Job? = null private var dataInit = false private val qrCodeResult = registerForActivityResult(QrCodeResult()) { it ?: return@registerForActivityResult @@ -173,37 +176,39 @@ class ReplaceRuleActivity : VMBaseActivity { - appDb.replaceRuleDao.liveDataAll() - } - searchKey.startsWith("group:") -> { - val key = searchKey.substringAfter("group:") - appDb.replaceRuleDao.liveDataGroupSearch("%$key%") - } - else -> { - appDb.replaceRuleDao.liveDataSearch("%$searchKey%") - } - }.apply { - observe(this@ReplaceRuleActivity, { + replaceRuleFlowJob?.cancel() + replaceRuleFlowJob = lifecycleScope.launch { + when { + searchKey.isNullOrEmpty() -> { + appDb.replaceRuleDao.liveDataAll() + } + searchKey.startsWith("group:") -> { + val key = searchKey.substringAfter("group:") + appDb.replaceRuleDao.liveDataGroupSearch("%$key%") + } + else -> { + appDb.replaceRuleDao.liveDataSearch("%$searchKey%") + } + }.collect { if (dataInit) { setResult(Activity.RESULT_OK) } adapter.setItems(it, adapter.diffItemCallBack) dataInit = true - }) + } } } private fun observeGroupData() { - appDb.replaceRuleDao.liveGroup().observe(this, { - groups.clear() - it.map { group -> - groups.addAll(group.splitNotBlank(AppPattern.splitGroupRegex)) + lifecycleScope.launch { + appDb.replaceRuleDao.liveGroup().collect { + groups.clear() + it.map { group -> + groups.addAll(group.splitNotBlank(AppPattern.splitGroupRegex)) + } + upGroupMenu() } - upGroupMenu() - }) + } } override fun onCompatOptionsItemSelected(item: MenuItem): Boolean { diff --git a/app/src/main/java/io/legado/app/ui/rss/subscription/RuleSubActivity.kt b/app/src/main/java/io/legado/app/ui/rss/subscription/RuleSubActivity.kt index 1209591d7..c81b5a387 100644 --- a/app/src/main/java/io/legado/app/ui/rss/subscription/RuleSubActivity.kt +++ b/app/src/main/java/io/legado/app/ui/rss/subscription/RuleSubActivity.kt @@ -4,7 +4,6 @@ import android.os.Bundle import android.view.Menu import android.view.MenuItem import androidx.core.view.isGone -import androidx.lifecycle.LiveData import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.ItemTouchHelper import io.legado.app.R @@ -22,6 +21,7 @@ import io.legado.app.utils.startActivity import io.legado.app.utils.toastOnUi import io.legado.app.utils.viewbindingdelegate.viewBinding import kotlinx.coroutines.Dispatchers.IO +import kotlinx.coroutines.flow.collect import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -33,7 +33,6 @@ class RuleSubActivity : BaseActivity(), override val binding by viewBinding(ActivityRuleSubBinding::inflate) private lateinit var adapter: RuleSubAdapter - private var liveData: LiveData>? = null override fun onActivityCreated(savedInstanceState: Bundle?) { initView() @@ -64,11 +63,11 @@ class RuleSubActivity : BaseActivity(), } private fun initData() { - liveData?.removeObservers(this) - liveData = appDb.ruleSubDao.observeAll() - liveData?.observe(this) { - binding.tvEmptyMsg.isGone = it.isNotEmpty() - adapter.setItems(it) + lifecycleScope.launch { + appDb.ruleSubDao.observeAll().collect { + binding.tvEmptyMsg.isGone = it.isNotEmpty() + adapter.setItems(it) + } } }