mirror of
https://github.com/gedoor/legado.git
synced 2024-09-01 09:34:25 +08:00
优化
This commit is contained in:
parent
9b49200a85
commit
5324dfcec3
@ -2,14 +2,21 @@ package io.legado.app.ui.book.source.manage
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.*
|
import android.view.Menu
|
||||||
|
import android.view.MenuItem
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import android.view.SubMenu
|
||||||
|
import android.view.WindowManager
|
||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.widget.PopupMenu
|
import androidx.appcompat.widget.PopupMenu
|
||||||
import androidx.appcompat.widget.SearchView
|
import androidx.appcompat.widget.SearchView
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.flowWithLifecycle
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper
|
import androidx.recyclerview.widget.ItemTouchHelper
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
@ -40,15 +47,31 @@ import io.legado.app.ui.widget.dialog.TextDialog
|
|||||||
import io.legado.app.ui.widget.recycler.DragSelectTouchHelper
|
import io.legado.app.ui.widget.recycler.DragSelectTouchHelper
|
||||||
import io.legado.app.ui.widget.recycler.ItemTouchCallback
|
import io.legado.app.ui.widget.recycler.ItemTouchCallback
|
||||||
import io.legado.app.ui.widget.recycler.VerticalDivider
|
import io.legado.app.ui.widget.recycler.VerticalDivider
|
||||||
import io.legado.app.utils.*
|
import io.legado.app.utils.ACache
|
||||||
|
import io.legado.app.utils.applyTint
|
||||||
|
import io.legado.app.utils.cnCompare
|
||||||
|
import io.legado.app.utils.dpToPx
|
||||||
|
import io.legado.app.utils.hideSoftInput
|
||||||
|
import io.legado.app.utils.isAbsUrl
|
||||||
|
import io.legado.app.utils.launch
|
||||||
|
import io.legado.app.utils.observeEvent
|
||||||
|
import io.legado.app.utils.sendToClip
|
||||||
|
import io.legado.app.utils.setEdgeEffectColor
|
||||||
|
import io.legado.app.utils.share
|
||||||
|
import io.legado.app.utils.showDialogFragment
|
||||||
|
import io.legado.app.utils.splitNotBlank
|
||||||
|
import io.legado.app.utils.startActivity
|
||||||
|
import io.legado.app.utils.toastOnUi
|
||||||
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
||||||
import kotlinx.coroutines.*
|
|
||||||
import kotlinx.coroutines.Dispatchers.IO
|
import kotlinx.coroutines.Dispatchers.IO
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.catch
|
import kotlinx.coroutines.flow.catch
|
||||||
import kotlinx.coroutines.flow.conflate
|
import kotlinx.coroutines.flow.conflate
|
||||||
import kotlinx.coroutines.flow.flow
|
|
||||||
import kotlinx.coroutines.flow.flowOn
|
import kotlinx.coroutines.flow.flowOn
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.coroutines.isActive
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 书源管理界面
|
* 书源管理界面
|
||||||
@ -67,6 +90,7 @@ class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceV
|
|||||||
binding.titleBar.findViewById(R.id.search_view)
|
binding.titleBar.findViewById(R.id.search_view)
|
||||||
}
|
}
|
||||||
private var sourceFlowJob: Job? = null
|
private var sourceFlowJob: Job? = null
|
||||||
|
private var checkMessageRefreshJob: Job? = null
|
||||||
private val groups = linkedSetOf<String>()
|
private val groups = linkedSetOf<String>()
|
||||||
private var groupMenu: SubMenu? = null
|
private var groupMenu: SubMenu? = null
|
||||||
override var sort = BookSourceSort.Default
|
override var sort = BookSourceSort.Default
|
||||||
@ -75,7 +99,6 @@ class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceV
|
|||||||
private set
|
private set
|
||||||
private var snackBar: Snackbar? = null
|
private var snackBar: Snackbar? = null
|
||||||
private var isPaused = false
|
private var isPaused = false
|
||||||
private var searchKey: String? = null
|
|
||||||
private val qrResult = registerForActivityResult(QrCodeResult()) {
|
private val qrResult = registerForActivityResult(QrCodeResult()) {
|
||||||
it ?: return@registerForActivityResult
|
it ?: return@registerForActivityResult
|
||||||
showDialogFragment(ImportBookSourceDialog(it))
|
showDialogFragment(ImportBookSourceDialog(it))
|
||||||
@ -256,7 +279,6 @@ class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceV
|
|||||||
|
|
||||||
|
|
||||||
private fun upBookSource(searchKey: String? = null) {
|
private fun upBookSource(searchKey: String? = null) {
|
||||||
this.searchKey = searchKey
|
|
||||||
sourceFlowJob?.cancel()
|
sourceFlowJob?.cancel()
|
||||||
sourceFlowJob = lifecycleScope.launch {
|
sourceFlowJob = lifecycleScope.launch {
|
||||||
when {
|
when {
|
||||||
@ -338,7 +360,7 @@ class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceV
|
|||||||
else -> data.reversed()
|
else -> data.reversed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.catch {
|
}.flowWithLifecycle(lifecycle).catch {
|
||||||
AppLog.put("书源界面更新书源出错", it)
|
AppLog.put("书源界面更新书源出错", it)
|
||||||
}.flowOn(IO).conflate().collect { data ->
|
}.flowOn(IO).conflate().collect { data ->
|
||||||
adapter.setItems(data, adapter.diffItemCallback, !Debug.isChecking)
|
adapter.setItems(data, adapter.diffItemCallback, !Debug.isChecking)
|
||||||
@ -403,7 +425,7 @@ class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceV
|
|||||||
R.id.menu_remove_group -> selectionRemoveFromGroups()
|
R.id.menu_remove_group -> selectionRemoveFromGroups()
|
||||||
R.id.menu_export_selection -> viewModel.saveToFile(
|
R.id.menu_export_selection -> viewModel.saveToFile(
|
||||||
adapter,
|
adapter,
|
||||||
searchKey,
|
searchView.query?.toString(),
|
||||||
sortAscending,
|
sortAscending,
|
||||||
sort
|
sort
|
||||||
) { file ->
|
) { file ->
|
||||||
@ -419,7 +441,7 @@ class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceV
|
|||||||
|
|
||||||
R.id.menu_share_source -> viewModel.saveToFile(
|
R.id.menu_share_source -> viewModel.saveToFile(
|
||||||
adapter,
|
adapter,
|
||||||
searchKey,
|
searchView.query?.toString(),
|
||||||
sortAscending,
|
sortAscending,
|
||||||
sort
|
sort
|
||||||
) {
|
) {
|
||||||
@ -452,7 +474,7 @@ class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceV
|
|||||||
val firstItem = adapterItems.indexOf(selectItems.firstOrNull())
|
val firstItem = adapterItems.indexOf(selectItems.firstOrNull())
|
||||||
val lastItem = adapterItems.indexOf(selectItems.lastOrNull())
|
val lastItem = adapterItems.indexOf(selectItems.lastOrNull())
|
||||||
Debug.isChecking = firstItem >= 0 && lastItem >= 0
|
Debug.isChecking = firstItem >= 0 && lastItem >= 0
|
||||||
checkMessageRefreshJob(firstItem, lastItem).start()
|
startCheckMessageRefreshJob(firstItem, lastItem)
|
||||||
}
|
}
|
||||||
neutralButton(R.string.check_source_config)
|
neutralButton(R.string.check_source_config)
|
||||||
cancelButton()
|
cancelButton()
|
||||||
@ -469,7 +491,7 @@ class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceV
|
|||||||
}
|
}
|
||||||
keepScreenOn(true)
|
keepScreenOn(true)
|
||||||
CheckSource.resume(this)
|
CheckSource.resume(this)
|
||||||
checkMessageRefreshJob(0, 0).start()
|
startCheckMessageRefreshJob(0, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("InflateParams")
|
@SuppressLint("InflateParams")
|
||||||
@ -558,11 +580,6 @@ class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceV
|
|||||||
.setAction(R.string.cancel) {
|
.setAction(R.string.cancel) {
|
||||||
CheckSource.stop(this)
|
CheckSource.stop(this)
|
||||||
Debug.finishChecking()
|
Debug.finishChecking()
|
||||||
adapter.notifyItemRangeChanged(
|
|
||||||
0,
|
|
||||||
adapter.itemCount,
|
|
||||||
bundleOf(Pair("checkSourceMessage", null))
|
|
||||||
)
|
|
||||||
}.apply { show() }
|
}.apply { show() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -570,6 +587,11 @@ class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceV
|
|||||||
keepScreenOn(false)
|
keepScreenOn(false)
|
||||||
snackBar?.dismiss()
|
snackBar?.dismiss()
|
||||||
snackBar = null
|
snackBar = null
|
||||||
|
adapter.notifyItemRangeChanged(
|
||||||
|
0,
|
||||||
|
adapter.itemCount,
|
||||||
|
bundleOf(Pair("checkSourceMessage", null))
|
||||||
|
)
|
||||||
groups.map { group ->
|
groups.map { group ->
|
||||||
if (group.contains("失效") && searchView.query.isEmpty()) {
|
if (group.contains("失效") && searchView.query.isEmpty()) {
|
||||||
searchView.setQuery("失效", true)
|
searchView.setQuery("失效", true)
|
||||||
@ -579,15 +601,11 @@ class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceV
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkMessageRefreshJob(firstItem: Int, lastItem: Int): Job {
|
private fun startCheckMessageRefreshJob(firstItem: Int, lastItem: Int) {
|
||||||
return lifecycleScope.async(start = CoroutineStart.LAZY) {
|
checkMessageRefreshJob?.cancel()
|
||||||
flow {
|
checkMessageRefreshJob = lifecycleScope.launch {
|
||||||
while (true) {
|
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||||
emit(Debug.isChecking)
|
while (isActive) {
|
||||||
delay(300L)
|
|
||||||
}
|
|
||||||
}.collect {
|
|
||||||
if (SystemUtils.isScreenOn() && !isPaused) {
|
|
||||||
if (lastItem == 0) {
|
if (lastItem == 0) {
|
||||||
adapter.notifyItemRangeChanged(
|
adapter.notifyItemRangeChanged(
|
||||||
0,
|
0,
|
||||||
@ -601,9 +619,10 @@ class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceV
|
|||||||
bundleOf(Pair("checkSourceMessage", null))
|
bundleOf(Pair("checkSourceMessage", null))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
if (!Debug.isChecking) {
|
||||||
|
checkMessageRefreshJob?.cancel()
|
||||||
}
|
}
|
||||||
if (!it) {
|
delay(300L)
|
||||||
this.cancel()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,10 @@ import android.os.Bundle
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.core.view.isGone
|
import androidx.core.view.isGone
|
||||||
import androidx.fragment.app.activityViewModels
|
import androidx.fragment.app.activityViewModels
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.flowWithLifecycle
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
@ -25,7 +28,6 @@ import io.legado.app.ui.book.audio.AudioPlayActivity
|
|||||||
import io.legado.app.ui.book.info.BookInfoActivity
|
import io.legado.app.ui.book.info.BookInfoActivity
|
||||||
import io.legado.app.ui.book.read.ReadBookActivity
|
import io.legado.app.ui.book.read.ReadBookActivity
|
||||||
import io.legado.app.ui.main.MainViewModel
|
import io.legado.app.ui.main.MainViewModel
|
||||||
import io.legado.app.utils.SystemUtils
|
|
||||||
import io.legado.app.utils.cnCompare
|
import io.legado.app.utils.cnCompare
|
||||||
import io.legado.app.utils.observeEvent
|
import io.legado.app.utils.observeEvent
|
||||||
import io.legado.app.utils.setEdgeEffectColor
|
import io.legado.app.utils.setEdgeEffectColor
|
||||||
@ -62,7 +64,7 @@ class BooksFragment() : BaseFragment(R.layout.fragment_books),
|
|||||||
private val bookshelfLayout by lazy { AppConfig.bookshelfLayout }
|
private val bookshelfLayout by lazy { AppConfig.bookshelfLayout }
|
||||||
private val booksAdapter: BaseBooksAdapter<*> by lazy {
|
private val booksAdapter: BaseBooksAdapter<*> by lazy {
|
||||||
if (bookshelfLayout == 0) {
|
if (bookshelfLayout == 0) {
|
||||||
BooksAdapterList(requireContext(), this, lifecycle)
|
BooksAdapterList(requireContext(), this, viewLifecycleOwner.lifecycle)
|
||||||
} else {
|
} else {
|
||||||
BooksAdapterGrid(requireContext(), this)
|
BooksAdapterGrid(requireContext(), this)
|
||||||
}
|
}
|
||||||
@ -154,7 +156,7 @@ class BooksFragment() : BaseFragment(R.layout.fragment_books),
|
|||||||
*/
|
*/
|
||||||
private fun upRecyclerData() {
|
private fun upRecyclerData() {
|
||||||
booksFlowJob?.cancel()
|
booksFlowJob?.cancel()
|
||||||
booksFlowJob = lifecycleScope.launch {
|
booksFlowJob = viewLifecycleOwner.lifecycleScope.launch {
|
||||||
appDb.bookDao.flowByGroup(groupId).map { list ->
|
appDb.bookDao.flowByGroup(groupId).map { list ->
|
||||||
//排序
|
//排序
|
||||||
when (bookSort) {
|
when (bookSort) {
|
||||||
@ -172,9 +174,9 @@ class BooksFragment() : BaseFragment(R.layout.fragment_books),
|
|||||||
|
|
||||||
else -> list.sortedByDescending { it.durChapterTime }
|
else -> list.sortedByDescending { it.durChapterTime }
|
||||||
}
|
}
|
||||||
}.flowOn(Dispatchers.Default).catch {
|
}.flowWithLifecycle(viewLifecycleOwner.lifecycle, Lifecycle.State.RESUMED).catch {
|
||||||
AppLog.put("书架更新出错", it)
|
AppLog.put("书架更新出错", it)
|
||||||
}.conflate().collect { list ->
|
}.conflate().flowOn(Dispatchers.Default).collect { list ->
|
||||||
binding.tvEmptyMsg.isGone = list.isNotEmpty()
|
binding.tvEmptyMsg.isGone = list.isNotEmpty()
|
||||||
binding.refreshLayout.isEnabled = enableRefresh && list.isNotEmpty()
|
binding.refreshLayout.isEnabled = enableRefresh && list.isNotEmpty()
|
||||||
booksAdapter.setItems(list)
|
booksAdapter.setItems(list)
|
||||||
@ -197,32 +199,20 @@ class BooksFragment() : BaseFragment(R.layout.fragment_books),
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
|
||||||
super.onPause()
|
|
||||||
upLastUpdateTimeJob?.cancel()
|
|
||||||
booksFlowJob?.cancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
startLastUpdateTimeJob()
|
|
||||||
upRecyclerData()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun startLastUpdateTimeJob() {
|
private fun startLastUpdateTimeJob() {
|
||||||
upLastUpdateTimeJob?.cancel()
|
upLastUpdateTimeJob?.cancel()
|
||||||
if (!AppConfig.showLastUpdateTime) {
|
if (!AppConfig.showLastUpdateTime) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
upLastUpdateTimeJob = lifecycleScope.launch {
|
upLastUpdateTimeJob = lifecycleScope.launch {
|
||||||
|
repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
||||||
while (isActive) {
|
while (isActive) {
|
||||||
if (SystemUtils.isScreenOn()) {
|
|
||||||
booksAdapter.upLastUpdateTime()
|
booksAdapter.upLastUpdateTime()
|
||||||
}
|
|
||||||
delay(30 * 1000)
|
delay(30 * 1000)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun getBooks(): List<Book> {
|
fun getBooks(): List<Book> {
|
||||||
return booksAdapter.getItems()
|
return booksAdapter.getItems()
|
||||||
|
@ -8,6 +8,8 @@ import android.view.View
|
|||||||
import androidx.appcompat.widget.SearchView
|
import androidx.appcompat.widget.SearchView
|
||||||
import androidx.core.view.isGone
|
import androidx.core.view.isGone
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.flowWithLifecycle
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
@ -34,7 +36,6 @@ import io.legado.app.utils.viewbindingdelegate.viewBinding
|
|||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers.IO
|
import kotlinx.coroutines.Dispatchers.IO
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.cancel
|
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.catch
|
import kotlinx.coroutines.flow.catch
|
||||||
import kotlinx.coroutines.flow.conflate
|
import kotlinx.coroutines.flow.conflate
|
||||||
@ -67,14 +68,13 @@ class ExploreFragment() : VMBaseFragment<ExploreViewModel>(R.layout.fragment_exp
|
|||||||
private val groups = linkedSetOf<String>()
|
private val groups = linkedSetOf<String>()
|
||||||
private var exploreFlowJob: Job? = null
|
private var exploreFlowJob: Job? = null
|
||||||
private var groupsMenu: SubMenu? = null
|
private var groupsMenu: SubMenu? = null
|
||||||
private var searchKey: String? = null
|
|
||||||
|
|
||||||
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
setSupportToolbar(binding.titleBar.toolbar)
|
setSupportToolbar(binding.titleBar.toolbar)
|
||||||
initSearchView()
|
initSearchView()
|
||||||
initRecyclerView()
|
initRecyclerView()
|
||||||
initGroupData()
|
initGroupData()
|
||||||
upExploreData(once = true)
|
upExploreData()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCompatCreateOptionsMenu(menu: Menu) {
|
override fun onCompatCreateOptionsMenu(menu: Menu) {
|
||||||
@ -87,7 +87,6 @@ class ExploreFragment() : VMBaseFragment<ExploreViewModel>(R.layout.fragment_exp
|
|||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
super.onPause()
|
super.onPause()
|
||||||
searchView.clearFocus()
|
searchView.clearFocus()
|
||||||
exploreFlowJob?.cancel()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initSearchView() {
|
private fun initSearchView() {
|
||||||
@ -126,7 +125,7 @@ class ExploreFragment() : VMBaseFragment<ExploreViewModel>(R.layout.fragment_exp
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun initGroupData() {
|
private fun initGroupData() {
|
||||||
lifecycleScope.launch {
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
appDb.bookSourceDao.flowExploreGroups().conflate().collect {
|
appDb.bookSourceDao.flowExploreGroups().conflate().collect {
|
||||||
groups.clear()
|
groups.clear()
|
||||||
groups.addAll(it)
|
groups.addAll(it)
|
||||||
@ -135,10 +134,9 @@ class ExploreFragment() : VMBaseFragment<ExploreViewModel>(R.layout.fragment_exp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun upExploreData(searchKey: String? = null, once: Boolean = false) {
|
private fun upExploreData(searchKey: String? = null) {
|
||||||
this.searchKey = searchKey
|
|
||||||
exploreFlowJob?.cancel()
|
exploreFlowJob?.cancel()
|
||||||
exploreFlowJob = lifecycleScope.launch {
|
exploreFlowJob = viewLifecycleOwner.lifecycleScope.launch {
|
||||||
when {
|
when {
|
||||||
searchKey.isNullOrBlank() -> {
|
searchKey.isNullOrBlank() -> {
|
||||||
appDb.bookSourceDao.flowExplore()
|
appDb.bookSourceDao.flowExplore()
|
||||||
@ -152,12 +150,11 @@ class ExploreFragment() : VMBaseFragment<ExploreViewModel>(R.layout.fragment_exp
|
|||||||
else -> {
|
else -> {
|
||||||
appDb.bookSourceDao.flowExplore(searchKey)
|
appDb.bookSourceDao.flowExplore(searchKey)
|
||||||
}
|
}
|
||||||
}.catch {
|
}.flowWithLifecycle(viewLifecycleOwner.lifecycle, Lifecycle.State.RESUMED).catch {
|
||||||
AppLog.put("发现界面更新数据出错", it)
|
AppLog.put("发现界面更新数据出错", it)
|
||||||
}.conflate().flowOn(IO).collect {
|
}.conflate().flowOn(IO).collect {
|
||||||
binding.tvEmptyMsg.isGone = it.isNotEmpty() || searchView.query.isNotEmpty()
|
binding.tvEmptyMsg.isGone = it.isNotEmpty() || searchView.query.isNotEmpty()
|
||||||
adapter.setItems(it, diffItemCallBack)
|
adapter.setItems(it, diffItemCallBack)
|
||||||
if (once) cancel()
|
|
||||||
delay(500)
|
delay(500)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -173,7 +170,7 @@ class ExploreFragment() : VMBaseFragment<ExploreViewModel>(R.layout.fragment_exp
|
|||||||
}
|
}
|
||||||
|
|
||||||
override val scope: CoroutineScope
|
override val scope: CoroutineScope
|
||||||
get() = lifecycleScope
|
get() = viewLifecycleOwner.lifecycleScope
|
||||||
|
|
||||||
override fun onCompatOptionsItemSelected(item: MenuItem) {
|
override fun onCompatOptionsItemSelected(item: MenuItem) {
|
||||||
super.onCompatOptionsItemSelected(item)
|
super.onCompatOptionsItemSelected(item)
|
||||||
@ -231,9 +228,4 @@ class ExploreFragment() : VMBaseFragment<ExploreViewModel>(R.layout.fragment_exp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
upExploreData(searchKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,11 @@
|
|||||||
package io.legado.app.ui.main.rss
|
package io.legado.app.ui.main.rss
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.appcompat.widget.PopupMenu
|
import androidx.appcompat.widget.PopupMenu
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import com.bumptech.glide.load.DataSource
|
|
||||||
import com.bumptech.glide.load.engine.GlideException
|
|
||||||
import com.bumptech.glide.load.resource.gif.GifDrawable
|
|
||||||
import com.bumptech.glide.request.RequestListener
|
|
||||||
import com.bumptech.glide.request.RequestOptions
|
import com.bumptech.glide.request.RequestOptions
|
||||||
import com.bumptech.glide.request.target.Target
|
|
||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.base.adapter.ItemViewHolder
|
import io.legado.app.base.adapter.ItemViewHolder
|
||||||
import io.legado.app.base.adapter.RecyclerAdapter
|
import io.legado.app.base.adapter.RecyclerAdapter
|
||||||
@ -39,35 +33,6 @@ class RssAdapter(context: Context, val callBack: CallBack, val lifecycle: Lifecy
|
|||||||
val options = RequestOptions()
|
val options = RequestOptions()
|
||||||
.set(OkHttpModelLoader.sourceOriginOption, item.sourceUrl)
|
.set(OkHttpModelLoader.sourceOriginOption, item.sourceUrl)
|
||||||
ImageLoader.load(lifecycle, item.sourceIcon)
|
ImageLoader.load(lifecycle, item.sourceIcon)
|
||||||
.listener(object : RequestListener<Drawable> {
|
|
||||||
|
|
||||||
override fun onLoadFailed(
|
|
||||||
e: GlideException?,
|
|
||||||
model: Any?,
|
|
||||||
target: Target<Drawable>,
|
|
||||||
isFirstResource: Boolean
|
|
||||||
): Boolean {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResourceReady(
|
|
||||||
resource: Drawable,
|
|
||||||
model: Any,
|
|
||||||
target: Target<Drawable>?,
|
|
||||||
dataSource: DataSource,
|
|
||||||
isFirstResource: Boolean
|
|
||||||
): Boolean {
|
|
||||||
if (resource is GifDrawable
|
|
||||||
&& !lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)
|
|
||||||
) {
|
|
||||||
ivIcon.post {
|
|
||||||
resource.stop()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
.apply(options)
|
.apply(options)
|
||||||
.centerCrop()
|
.centerCrop()
|
||||||
.placeholder(R.drawable.image_rss)
|
.placeholder(R.drawable.image_rss)
|
||||||
|
@ -7,6 +7,8 @@ import android.view.SubMenu
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.appcompat.widget.SearchView
|
import androidx.appcompat.widget.SearchView
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.flowWithLifecycle
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.base.VMBaseFragment
|
import io.legado.app.base.VMBaseFragment
|
||||||
@ -58,7 +60,7 @@ class RssFragment() : VMBaseFragment<RssViewModel>(R.layout.fragment_rss),
|
|||||||
|
|
||||||
private val binding by viewBinding(FragmentRssBinding::bind)
|
private val binding by viewBinding(FragmentRssBinding::bind)
|
||||||
override val viewModel by viewModels<RssViewModel>()
|
override val viewModel by viewModels<RssViewModel>()
|
||||||
private val adapter by lazy { RssAdapter(requireContext(), this, lifecycle) }
|
private val adapter by lazy { RssAdapter(requireContext(), this, viewLifecycleOwner.lifecycle) }
|
||||||
private val searchView: SearchView by lazy {
|
private val searchView: SearchView by lazy {
|
||||||
binding.titleBar.findViewById(R.id.search_view)
|
binding.titleBar.findViewById(R.id.search_view)
|
||||||
}
|
}
|
||||||
@ -142,10 +144,11 @@ class RssFragment() : VMBaseFragment<RssViewModel>(R.layout.fragment_rss),
|
|||||||
|
|
||||||
private fun initGroupData() {
|
private fun initGroupData() {
|
||||||
groupsFlowJob?.cancel()
|
groupsFlowJob?.cancel()
|
||||||
groupsFlowJob = lifecycleScope.launch {
|
groupsFlowJob = viewLifecycleOwner.lifecycleScope.launch {
|
||||||
appDb.rssSourceDao.flowGroupEnabled().catch {
|
appDb.rssSourceDao.flowGroupEnabled().catch {
|
||||||
AppLog.put("订阅界面获取分组数据失败\n${it.localizedMessage}", it)
|
AppLog.put("订阅界面获取分组数据失败\n${it.localizedMessage}", it)
|
||||||
}.flowOn(IO).conflate().collect {
|
}.flowWithLifecycle(viewLifecycleOwner.lifecycle, Lifecycle.State.RESUMED)
|
||||||
|
.flowOn(IO).conflate().collect {
|
||||||
groups.clear()
|
groups.clear()
|
||||||
it.map { group ->
|
it.map { group ->
|
||||||
groups.addAll(group.splitNotBlank(AppPattern.splitGroupRegex))
|
groups.addAll(group.splitNotBlank(AppPattern.splitGroupRegex))
|
||||||
@ -157,7 +160,7 @@ class RssFragment() : VMBaseFragment<RssViewModel>(R.layout.fragment_rss),
|
|||||||
|
|
||||||
private fun upRssFlowJob(searchKey: String? = null) {
|
private fun upRssFlowJob(searchKey: String? = null) {
|
||||||
rssFlowJob?.cancel()
|
rssFlowJob?.cancel()
|
||||||
rssFlowJob = lifecycleScope.launch {
|
rssFlowJob = viewLifecycleOwner.lifecycleScope.launch {
|
||||||
when {
|
when {
|
||||||
searchKey.isNullOrEmpty() -> appDb.rssSourceDao.flowEnabled()
|
searchKey.isNullOrEmpty() -> appDb.rssSourceDao.flowEnabled()
|
||||||
searchKey.startsWith("group:") -> {
|
searchKey.startsWith("group:") -> {
|
||||||
@ -166,7 +169,7 @@ class RssFragment() : VMBaseFragment<RssViewModel>(R.layout.fragment_rss),
|
|||||||
}
|
}
|
||||||
|
|
||||||
else -> appDb.rssSourceDao.flowEnabled(searchKey)
|
else -> appDb.rssSourceDao.flowEnabled(searchKey)
|
||||||
}.catch {
|
}.flowWithLifecycle(viewLifecycleOwner.lifecycle, Lifecycle.State.RESUMED).catch {
|
||||||
AppLog.put("订阅界面更新数据出错", it)
|
AppLog.put("订阅界面更新数据出错", it)
|
||||||
}.flowOn(IO).collect {
|
}.flowOn(IO).collect {
|
||||||
adapter.setItems(it)
|
adapter.setItems(it)
|
||||||
|
Loading…
Reference in New Issue
Block a user