阅读动画
This commit is contained in:
@@ -10,7 +10,6 @@ import android.view.ViewConfiguration
|
|||||||
import androidx.core.app.ActivityOptionsCompat
|
import androidx.core.app.ActivityOptionsCompat
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
import androidx.core.view.doOnPreDraw
|
|
||||||
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.Lifecycle
|
||||||
@@ -116,10 +115,6 @@ class BooksFragment() : BaseFragment(R.layout.fragment_books),
|
|||||||
private var enableRefresh = true
|
private var enableRefresh = true
|
||||||
|
|
||||||
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
postponeEnterTransition()
|
|
||||||
view.doOnPreDraw {
|
|
||||||
startPostponedEnterTransition()
|
|
||||||
}
|
|
||||||
arguments?.let {
|
arguments?.let {
|
||||||
position = it.getInt("position", 0)
|
position = it.getInt("position", 0)
|
||||||
groupId = it.getLong("groupId", -1)
|
groupId = it.getLong("groupId", -1)
|
||||||
@@ -248,11 +243,10 @@ class BooksFragment() : BaseFragment(R.layout.fragment_books),
|
|||||||
).catch {
|
).catch {
|
||||||
AppLog.put("书架更新出错", it)
|
AppLog.put("书架更新出错", it)
|
||||||
}.conflate().flowOn(Dispatchers.Default).collect { list ->
|
}.conflate().flowOn(Dispatchers.Default).collect { list ->
|
||||||
if (view == null) return@collect
|
|
||||||
binding.emptyView.isGone = list.isNotEmpty()
|
binding.emptyView.isGone = list.isNotEmpty()
|
||||||
binding.refreshLayout.isEnabled = enableRefresh && list.isNotEmpty()
|
binding.refreshLayout.isEnabled = enableRefresh && list.isNotEmpty()
|
||||||
booksAdapter.setItems(list)
|
booksAdapter.setItems(list)
|
||||||
delay(500)
|
delay(100)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import androidx.appcompat.widget.SearchView
|
|||||||
import androidx.core.app.ActivityOptionsCompat
|
import androidx.core.app.ActivityOptionsCompat
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
import androidx.core.view.doOnPreDraw
|
|
||||||
import androidx.core.view.isGone
|
import androidx.core.view.isGone
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
@@ -52,7 +51,6 @@ import io.legado.app.utils.showDialogFragment
|
|||||||
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
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.flowOn
|
import kotlinx.coroutines.flow.flowOn
|
||||||
@@ -120,10 +118,6 @@ class BookshelfFragment2() : BaseBookshelfFragment(R.layout.fragment_bookshelf2)
|
|||||||
|
|
||||||
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
setSupportToolbar(binding.topBar)
|
setSupportToolbar(binding.topBar)
|
||||||
postponeEnterTransition()
|
|
||||||
view.doOnPreDraw {
|
|
||||||
startPostponedEnterTransition()
|
|
||||||
}
|
|
||||||
initRecyclerView()
|
initRecyclerView()
|
||||||
initBookGroupData()
|
initBookGroupData()
|
||||||
initAllBooksData()
|
initAllBooksData()
|
||||||
@@ -305,11 +299,10 @@ class BookshelfFragment2() : BaseBookshelfFragment(R.layout.fragment_bookshelf2)
|
|||||||
).catch {
|
).catch {
|
||||||
AppLog.put("书架更新出错", it)
|
AppLog.put("书架更新出错", it)
|
||||||
}.conflate().flowOn(Dispatchers.Default).collect { list ->
|
}.conflate().flowOn(Dispatchers.Default).collect { list ->
|
||||||
if (view == null) return@collect
|
books = list
|
||||||
binding.emptyView.isGone = list.isNotEmpty()
|
|
||||||
binding.refreshLayout.isEnabled = enableRefresh && list.isNotEmpty()
|
|
||||||
booksAdapter.updateItems()
|
booksAdapter.updateItems()
|
||||||
delay(500)
|
binding.emptyView.isGone = getItemCount() > 0
|
||||||
|
binding.refreshLayout.isEnabled = enableRefresh && getItemCount() > 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
@@ -12,6 +12,13 @@ import io.legado.app.data.entities.Book
|
|||||||
abstract class BaseBooksAdapter<VB : ViewBinding>(context: Context) :
|
abstract class BaseBooksAdapter<VB : ViewBinding>(context: Context) :
|
||||||
DiffRecyclerAdapter<Book, VB>(context) {
|
DiffRecyclerAdapter<Book, VB>(context) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
setHasStableIds(true)
|
||||||
|
}
|
||||||
|
override fun getItemId(position: Int): Long {
|
||||||
|
return getItems()[position].bookUrl.hashCode().toLong()
|
||||||
|
}
|
||||||
|
|
||||||
override val keepScrollPosition = true
|
override val keepScrollPosition = true
|
||||||
|
|
||||||
override val diffItemCallback: DiffUtil.ItemCallback<Book> =
|
override val diffItemCallback: DiffUtil.ItemCallback<Book> =
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import kotlinx.coroutines.flow.FlowCollector
|
|||||||
import kotlinx.coroutines.flow.buffer
|
import kotlinx.coroutines.flow.buffer
|
||||||
import kotlinx.coroutines.flow.callbackFlow
|
import kotlinx.coroutines.flow.callbackFlow
|
||||||
import kotlinx.coroutines.flow.channelFlow
|
import kotlinx.coroutines.flow.channelFlow
|
||||||
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.conflate
|
import kotlinx.coroutines.flow.conflate
|
||||||
import kotlinx.coroutines.flow.filterNotNull
|
import kotlinx.coroutines.flow.filterNotNull
|
||||||
import kotlinx.coroutines.flow.firstOrNull
|
import kotlinx.coroutines.flow.firstOrNull
|
||||||
@@ -235,29 +236,16 @@ fun <T> Flow<T>.flowWithLifecycleAndDatabaseChange(
|
|||||||
|
|
||||||
fun <T> Flow<T>.flowWithLifecycleAndDatabaseChangeFirst(
|
fun <T> Flow<T>.flowWithLifecycleAndDatabaseChangeFirst(
|
||||||
lifecycle: Lifecycle,
|
lifecycle: Lifecycle,
|
||||||
minActiveState: Lifecycle.State = Lifecycle.State.STARTED,
|
minActiveState: Lifecycle.State = Lifecycle.State.RESUMED,
|
||||||
table: String
|
table: String
|
||||||
): Flow<T> = callbackFlow {
|
): Flow<T> = callbackFlow {
|
||||||
var update = 0
|
val invalidationFlow = appDb.invalidationTracker
|
||||||
val isActive = lifecycle.currentState.isAtLeast(minActiveState)
|
.createFlow(table, emitInitialState = true)
|
||||||
val channel = appDb.invalidationTracker
|
|
||||||
.createFlow(table, emitInitialState = isActive)
|
|
||||||
.conflate()
|
.conflate()
|
||||||
.onEach { update++ }
|
|
||||||
.produceIn(this)
|
|
||||||
if (!isActive) {
|
|
||||||
firstOrNull()?.let {
|
|
||||||
send(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lifecycle.repeatOnLifecycle(minActiveState) {
|
lifecycle.repeatOnLifecycle(minActiveState) {
|
||||||
if (update == 0) {
|
combine(this@flowWithLifecycleAndDatabaseChangeFirst, invalidationFlow) { data, _ -> data }
|
||||||
channel.receive()
|
.collect { send(it) }
|
||||||
}
|
|
||||||
this@flowWithLifecycleAndDatabaseChangeFirst.collect {
|
|
||||||
update = 0
|
|
||||||
send(it)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
close()
|
close()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user