diff --git a/app/src/main/java/io/legado/app/data/dao/RssSourceDao.kt b/app/src/main/java/io/legado/app/data/dao/RssSourceDao.kt index deaa45726..6abd2f847 100644 --- a/app/src/main/java/io/legado/app/data/dao/RssSourceDao.kt +++ b/app/src/main/java/io/legado/app/data/dao/RssSourceDao.kt @@ -1,8 +1,8 @@ package io.legado.app.data.dao -import androidx.lifecycle.LiveData import androidx.room.* import io.legado.app.data.entities.RssSource +import kotlinx.coroutines.flow.Flow @Dao interface RssSourceDao { @@ -20,25 +20,32 @@ interface RssSourceDao { val size: Int @Query("SELECT * FROM rssSources order by customOrder") - fun liveAll(): LiveData> + fun liveAll(): Flow> @Query("SELECT * FROM rssSources where sourceName like :key or sourceUrl like :key or sourceGroup like :key order by customOrder") - fun liveSearch(key: String): LiveData> + fun liveSearch(key: String): Flow> @Query("SELECT * FROM rssSources where sourceGroup like :key order by customOrder") - fun liveGroupSearch(key: String): LiveData> + fun liveGroupSearch(key: String): Flow> @Query("SELECT * FROM rssSources where enabled = 1 order by customOrder") - fun liveEnabled(): LiveData> - - @Query("SELECT * FROM rssSources where enabled = 1 and (sourceName like :searchKey or sourceGroup like :searchKey or sourceUrl like :searchKey) order by customOrder") - fun liveEnabled(searchKey: String): LiveData> + fun liveEnabled(): Flow> + + @Query( + """ + SELECT * FROM rssSources + where enabled = 1 + and (sourceName like :searchKey or sourceGroup like :searchKey or sourceUrl like :searchKey) + order by customOrder + """ + ) + fun liveEnabled(searchKey: String): Flow> @Query("SELECT * FROM rssSources where enabled = 1 and sourceGroup like :searchKey order by customOrder") - fun liveEnabledByGroup(searchKey: String): LiveData> + fun liveEnabledByGroup(searchKey: String): Flow> @Query("select distinct sourceGroup from rssSources where trim(sourceGroup) <> ''") - fun liveGroup(): LiveData> + fun liveGroup(): Flow> @get:Query("select distinct sourceGroup from rssSources where trim(sourceGroup) <> ''") val allGroup: List diff --git a/app/src/main/java/io/legado/app/ui/main/rss/RssFragment.kt b/app/src/main/java/io/legado/app/ui/main/rss/RssFragment.kt index 39c9143d5..0d20d7252 100644 --- a/app/src/main/java/io/legado/app/ui/main/rss/RssFragment.kt +++ b/app/src/main/java/io/legado/app/ui/main/rss/RssFragment.kt @@ -7,7 +7,6 @@ import android.view.SubMenu import android.view.View import androidx.appcompat.widget.SearchView import androidx.fragment.app.viewModels -import androidx.lifecycle.LiveData import io.legado.app.R import io.legado.app.base.VMBaseFragment import io.legado.app.constant.AppPattern @@ -29,6 +28,9 @@ import io.legado.app.utils.openUrl import io.legado.app.utils.splitNotBlank import io.legado.app.utils.startActivity import io.legado.app.utils.viewbindingdelegate.viewBinding +import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.launch /** @@ -40,9 +42,8 @@ class RssFragment : VMBaseFragment(R.layout.fragment_rss), override val viewModel by viewModels() private lateinit var adapter: RssAdapter private lateinit var searchView: SearchView - private var liveRssData: LiveData>? = null + private var rssFlowJob: Job? = null private val groups = linkedSetOf() - private var liveGroup: LiveData>? = null private var groupsMenu: SubMenu? = null override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { @@ -51,7 +52,7 @@ class RssFragment : VMBaseFragment(R.layout.fragment_rss), initSearchView() initRecyclerView() initGroupData() - initData() + upRssFlowJob() } override fun onCompatCreateOptionsMenu(menu: Menu) { @@ -97,7 +98,7 @@ class RssFragment : VMBaseFragment(R.layout.fragment_rss), } override fun onQueryTextChange(newText: String?): Boolean { - initData(newText) + upRssFlowJob(newText) return false } }) @@ -118,32 +119,32 @@ class RssFragment : VMBaseFragment(R.layout.fragment_rss), } } - private fun initData(searchKey: String? = null) { - liveRssData?.removeObservers(this) - liveRssData = when { - searchKey.isNullOrEmpty() -> appDb.rssSourceDao.liveEnabled() - searchKey.startsWith("group:") -> { - val key = searchKey.substringAfter("group:") - appDb.rssSourceDao.liveEnabledByGroup("%$key%") + private fun initGroupData() { + launch { + appDb.rssSourceDao.liveGroup().collect { + groups.clear() + it.map { group -> + groups.addAll(group.splitNotBlank(AppPattern.splitGroupRegex)) + } + upGroupsMenu() } - else -> appDb.rssSourceDao.liveEnabled("%$searchKey%") - }.apply { - observe(viewLifecycleOwner, { - adapter.setItems(it) - }) } } - private fun initGroupData() { - liveGroup?.removeObservers(viewLifecycleOwner) - liveGroup = appDb.rssSourceDao.liveGroup() - liveGroup?.observe(viewLifecycleOwner, { - groups.clear() - it.map { group -> - groups.addAll(group.splitNotBlank(AppPattern.splitGroupRegex)) + private fun upRssFlowJob(searchKey: String? = null) { + rssFlowJob?.cancel() + rssFlowJob = launch { + when { + searchKey.isNullOrEmpty() -> appDb.rssSourceDao.liveEnabled() + searchKey.startsWith("group:") -> { + val key = searchKey.substringAfter("group:") + appDb.rssSourceDao.liveEnabledByGroup("%$key%") + } + else -> appDb.rssSourceDao.liveEnabled("%$searchKey%") + }.collect { + adapter.setItems(it) } - upGroupsMenu() - }) + } } override fun openRss(rssSource: RssSource) { diff --git a/app/src/main/java/io/legado/app/ui/rss/source/manage/GroupManageDialog.kt b/app/src/main/java/io/legado/app/ui/rss/source/manage/GroupManageDialog.kt index 0c4286e15..806e8122d 100644 --- a/app/src/main/java/io/legado/app/ui/rss/source/manage/GroupManageDialog.kt +++ b/app/src/main/java/io/legado/app/ui/rss/source/manage/GroupManageDialog.kt @@ -26,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 : BaseDialogFragment(), Toolbar.OnMenuItemClickListener { @@ -62,13 +64,19 @@ class GroupManageDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener tvOk.setOnClickListener { dismissAllowingStateLoss() } - appDb.rssSourceDao.liveGroup().observe(viewLifecycleOwner, { - val groups = linkedSetOf() - it.map { group -> - groups.addAll(group.splitNotBlank(AppPattern.splitGroupRegex)) + initData() + } + + private fun initData() { + launch { + appDb.rssSourceDao.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/rss/source/manage/RssSourceActivity.kt b/app/src/main/java/io/legado/app/ui/rss/source/manage/RssSourceActivity.kt index e90a1f287..23ecb9f17 100644 --- a/app/src/main/java/io/legado/app/ui/rss/source/manage/RssSourceActivity.kt +++ b/app/src/main/java/io/legado/app/ui/rss/source/manage/RssSourceActivity.kt @@ -10,7 +10,6 @@ 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.recyclerview.widget.ItemTouchHelper import io.legado.app.R import io.legado.app.base.VMBaseActivity @@ -35,6 +34,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 /** @@ -49,7 +51,7 @@ class RssSourceActivity : VMBaseActivity() private val importRecordKey = "rssSourceRecordKey" private lateinit var adapter: RssSourceAdapter - private var sourceLiveData: LiveData>? = null + private var sourceFlowJob: Job? = null private var groups = hashSetOf() private var groupMenu: SubMenu? = null private val qrCodeResult = registerForActivityResult(QrCodeResult()) { @@ -86,8 +88,8 @@ class RssSourceActivity : VMBaseActivity - groups.addAll(group.splitNotBlank(AppPattern.splitGroupRegex)) + private fun initGroupFlow() { + launch { + appDb.rssSourceDao.liveGroup().collect { + groups.clear() + it.map { group -> + groups.addAll(group.splitNotBlank(AppPattern.splitGroupRegex)) + } + upGroupMenu() } - upGroupMenu() - }) + } } override fun selectAll(selectAll: Boolean) { @@ -224,23 +228,23 @@ class RssSourceActivity : VMBaseActivity { - appDb.rssSourceDao.liveAll() - } - searchKey.startsWith("group:") -> { - val key = searchKey.substringAfter("group:") - appDb.rssSourceDao.liveGroupSearch("%$key%") - } - else -> { - appDb.rssSourceDao.liveSearch("%$searchKey%") - } - }.apply { - observe(this@RssSourceActivity, { + private fun upSourceFlow(searchKey: String? = null) { + sourceFlowJob?.cancel() + sourceFlowJob = launch { + when { + searchKey.isNullOrBlank() -> { + appDb.rssSourceDao.liveAll() + } + searchKey.startsWith("group:") -> { + val key = searchKey.substringAfter("group:") + appDb.rssSourceDao.liveGroupSearch("%$key%") + } + else -> { + appDb.rssSourceDao.liveSearch("%$searchKey%") + } + }.collect { adapter.setItems(it, adapter.diffItemCallback) - }) + } } }