MangaController optimizations (#6089)

* MangaController: Fix ignored stable ids

* MangaController: Replace notifyDataSetChanged

* ChaptersSettingsSheet: Optimizations
This commit is contained in:
Ivan Iskandar 2021-10-13 20:23:38 +07:00 committed by GitHub
parent e621f4e2fa
commit 684965f3e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 52 additions and 46 deletions

View File

@ -85,7 +85,6 @@ import eu.kanade.tachiyomi.ui.webview.WebViewActivity
import eu.kanade.tachiyomi.util.chapter.NoChaptersException import eu.kanade.tachiyomi.util.chapter.NoChaptersException
import eu.kanade.tachiyomi.util.hasCustomCover import eu.kanade.tachiyomi.util.hasCustomCover
import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.launchUI
import eu.kanade.tachiyomi.util.storage.getUriCompat import eu.kanade.tachiyomi.util.storage.getUriCompat
import eu.kanade.tachiyomi.util.system.logcat import eu.kanade.tachiyomi.util.system.logcat
import eu.kanade.tachiyomi.util.system.toShareIntent import eu.kanade.tachiyomi.util.system.toShareIntent
@ -249,13 +248,21 @@ class MangaController :
if (manga == null || source == null) return if (manga == null || source == null) return
// Init RecyclerView and adapter // Init RecyclerView and adapter
mangaInfoAdapter = MangaInfoHeaderAdapter(this, fromSource, binding.infoRecycler != null) mangaInfoAdapter = MangaInfoHeaderAdapter(this, fromSource, binding.infoRecycler != null).apply {
chaptersHeaderAdapter = MangaChaptersHeaderAdapter(this) setHasStableIds(true)
}
chaptersHeaderAdapter = MangaChaptersHeaderAdapter(this).apply {
setHasStableIds(true)
}
chaptersAdapter = ChaptersAdapter(this, view.context) chaptersAdapter = ChaptersAdapter(this, view.context)
// Phone layout // Phone layout
binding.fullRecycler?.let { binding.fullRecycler?.let {
it.adapter = ConcatAdapter(mangaInfoAdapter, chaptersHeaderAdapter, chaptersAdapter) val config = ConcatAdapter.Config.Builder()
.setIsolateViewTypes(true)
.setStableIdMode(ConcatAdapter.Config.StableIdMode.SHARED_STABLE_IDS)
.build()
it.adapter = ConcatAdapter(config, mangaInfoAdapter, chaptersHeaderAdapter, chaptersAdapter)
// Skips directly to chapters list if navigated to from the library // Skips directly to chapters list if navigated to from the library
it.post { it.post {
@ -318,7 +325,6 @@ class MangaController :
settingsSheet = ChaptersSettingsSheet(router, presenter) { group -> settingsSheet = ChaptersSettingsSheet(router, presenter) { group ->
if (group is ChaptersSettingsSheet.Filter.FilterGroup) { if (group is ChaptersSettingsSheet.Filter.FilterGroup) {
updateFilterIconState() updateFilterIconState()
chaptersAdapter?.notifyDataSetChanged()
} }
} }
@ -620,7 +626,7 @@ class MangaController :
} }
} }
} }
mangaInfoAdapter?.notifyDataSetChanged() mangaInfoAdapter?.update()
} }
fun onCategoriesClick() { fun onCategoriesClick() {
@ -818,7 +824,7 @@ class MangaController :
override fun deleteMangaCover(manga: Manga) { override fun deleteMangaCover(manga: Manga) {
presenter.deleteCustomCover(manga) presenter.deleteCustomCover(manga)
mangaInfoAdapter?.notifyDataSetChanged() mangaInfoAdapter?.notifyItemChanged(0, manga)
destroyActionModeIfNeeded() destroyActionModeIfNeeded()
} }
@ -832,7 +838,7 @@ class MangaController :
} }
fun onSetCoverSuccess() { fun onSetCoverSuccess() {
mangaInfoAdapter?.notifyDataSetChanged() mangaInfoAdapter?.notifyItemChanged(0, this)
(dialog as? MangaFullCoverDialog)?.setImage(manga) (dialog as? MangaFullCoverDialog)?.setImage(manga)
activity?.toast(R.string.cover_updated) activity?.toast(R.string.cover_updated)
} }
@ -943,19 +949,20 @@ class MangaController :
val lastClickPosition = lastClickPositionStack.peek()!! val lastClickPosition = lastClickPositionStack.peek()!!
when { when {
lastClickPosition == -1 -> setSelection(position) lastClickPosition == -1 -> setSelection(position)
lastClickPosition > position -> lastClickPosition > position -> {
for (i in position until lastClickPosition) for (i in position until lastClickPosition) setSelection(i)
setSelection(i) chaptersAdapter?.notifyItemRangeChanged(position, lastClickPosition, position)
lastClickPosition < position -> }
for (i in lastClickPosition + 1..position) lastClickPosition < position -> {
setSelection(i) for (i in lastClickPosition + 1..position) setSelection(i)
chaptersAdapter?.notifyItemRangeChanged(lastClickPosition + 1, position, position)
}
else -> setSelection(position) else -> setSelection(position)
} }
if (lastClickPosition != position) { if (lastClickPosition != position) {
lastClickPositionStack.remove(position) // move to top if already exists lastClickPositionStack.remove(position) // move to top if already exists
lastClickPositionStack.push(position) lastClickPositionStack.push(position)
} }
chaptersAdapter?.notifyDataSetChanged()
} }
fun showSettingsSheet() { fun showSettingsSheet() {
@ -968,7 +975,6 @@ class MangaController :
val adapter = chaptersAdapter ?: return val adapter = chaptersAdapter ?: return
val item = adapter.getItem(position) ?: return val item = adapter.getItem(position) ?: return
adapter.toggleSelection(position) adapter.toggleSelection(position)
adapter.notifyDataSetChanged()
if (adapter.isSelected(position)) { if (adapter.isSelected(position)) {
selectedChapters.add(item) selectedChapters.add(item)
} else { } else {
@ -1101,11 +1107,11 @@ class MangaController :
selectedChapters.clear() selectedChapters.clear()
for (i in 0..adapter.itemCount) { for (i in 0..adapter.itemCount) {
adapter.toggleSelection(i) adapter.toggleSelection(i)
adapter.notifyItemChanged(i, i)
} }
selectedChapters.addAll(adapter.selectedPositions.mapNotNull { adapter.getItem(it) }) selectedChapters.addAll(adapter.selectedPositions.mapNotNull { adapter.getItem(it) })
actionMode?.invalidate() actionMode?.invalidate()
adapter.notifyDataSetChanged()
} }
private fun markAsRead(chapters: List<ChapterItem>) { private fun markAsRead(chapters: List<ChapterItem>) {
@ -1172,10 +1178,7 @@ class MangaController :
fun onChaptersDeleted(chapters: List<ChapterItem>) { fun onChaptersDeleted(chapters: List<ChapterItem>) {
// this is needed so the downloaded text gets removed from the item // this is needed so the downloaded text gets removed from the item
chapters.forEach { chapters.forEach {
chaptersAdapter?.updateItem(it) chaptersAdapter?.updateItem(it, it)
}
launchUI {
chaptersAdapter?.notifyDataSetChanged()
} }
} }

View File

@ -718,6 +718,7 @@ class MangaPresenter(
fun setDisplayMode(mode: Int) { fun setDisplayMode(mode: Int) {
manga.displayMode = mode manga.displayMode = mode
db.updateChapterFlags(manga).executeAsBlocking() db.updateChapterFlags(manga).executeAsBlocking()
refreshChapters()
} }
/** /**

View File

@ -116,7 +116,7 @@ class ChaptersSettingsSheet(
} }
initModels() initModels()
item.group.items.forEach { adapter.notifyItemChanged(it) } adapter.notifyItemChanged(items.indexOf(item), item)
} }
} }
} }
@ -158,18 +158,18 @@ class ChaptersSettingsSheet(
} }
override fun onItemClicked(item: Item) { override fun onItemClicked(item: Item) {
item as Item.MultiStateGroup items.forEachIndexed { i, multiSort ->
val prevState = item.state multiSort.state = if (multiSort == item) {
when (item.state) {
item.group.items.forEach { Item.MultiSort.SORT_NONE -> Item.MultiSort.SORT_ASC
(it as Item.MultiStateGroup).state = Item.MultiSort.SORT_ASC -> Item.MultiSort.SORT_DESC
Item.MultiSort.SORT_DESC -> Item.MultiSort.SORT_ASC
else -> throw Exception("Unknown state")
}
} else {
Item.MultiSort.SORT_NONE Item.MultiSort.SORT_NONE
} }
item.state = when (prevState) { adapter.notifyItemChanged(i, multiSort)
Item.MultiSort.SORT_NONE -> Item.MultiSort.SORT_ASC
Item.MultiSort.SORT_ASC -> Item.MultiSort.SORT_DESC
Item.MultiSort.SORT_DESC -> Item.MultiSort.SORT_ASC
else -> throw Exception("Unknown state")
} }
when (item) { when (item) {
@ -180,8 +180,6 @@ class ChaptersSettingsSheet(
} }
presenter.reverseSortOrder() presenter.reverseSortOrder()
item.group.items.forEach { adapter.notifyItemChanged(it) }
} }
} }
} }
@ -215,16 +213,16 @@ class ChaptersSettingsSheet(
item as Item.Radio item as Item.Radio
if (item.checked) return if (item.checked) return
item.group.items.forEach { (it as Item.Radio).checked = false } items.forEachIndexed { index, radio ->
item.checked = true radio.checked = item == radio
adapter.notifyItemChanged(index, radio)
}
when (item) { when (item) {
displayTitle -> presenter.setDisplayMode(Manga.CHAPTER_DISPLAY_NAME) displayTitle -> presenter.setDisplayMode(Manga.CHAPTER_DISPLAY_NAME)
displayChapterNum -> presenter.setDisplayMode(Manga.CHAPTER_DISPLAY_NUMBER) displayChapterNum -> presenter.setDisplayMode(Manga.CHAPTER_DISPLAY_NUMBER)
else -> throw NotImplementedError("Unknown display mode") else -> throw NotImplementedError("Unknown display mode")
} }
item.group.items.forEach { adapter.notifyItemChanged(it) }
} }
} }
} }

View File

@ -30,20 +30,20 @@ class MangaChaptersHeaderAdapter(
override fun getItemCount(): Int = 1 override fun getItemCount(): Int = 1
override fun getItemId(position: Int): Long = hashCode().toLong()
override fun onBindViewHolder(holder: HeaderViewHolder, position: Int) { override fun onBindViewHolder(holder: HeaderViewHolder, position: Int) {
holder.bind() holder.bind()
} }
fun setNumChapters(numChapters: Int) { fun setNumChapters(numChapters: Int) {
this.numChapters = numChapters this.numChapters = numChapters
notifyItemChanged(0, this)
notifyDataSetChanged()
} }
fun setHasActiveFilters(hasActiveFilters: Boolean) { fun setHasActiveFilters(hasActiveFilters: Boolean) {
this.hasActiveFilters = hasActiveFilters this.hasActiveFilters = hasActiveFilters
notifyItemChanged(0, this)
notifyDataSetChanged()
} }
inner class HeaderViewHolder(private val view: View) : RecyclerView.ViewHolder(view) { inner class HeaderViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {

View File

@ -56,6 +56,8 @@ class MangaInfoHeaderAdapter(
override fun getItemCount(): Int = 1 override fun getItemCount(): Int = 1
override fun getItemId(position: Int): Long = hashCode().toLong()
override fun onBindViewHolder(holder: HeaderViewHolder, position: Int) { override fun onBindViewHolder(holder: HeaderViewHolder, position: Int) {
holder.bind() holder.bind()
} }
@ -69,14 +71,16 @@ class MangaInfoHeaderAdapter(
fun update(manga: Manga, source: Source) { fun update(manga: Manga, source: Source) {
this.manga = manga this.manga = manga
this.source = source this.source = source
update()
}
notifyDataSetChanged() fun update() {
notifyItemChanged(0, this)
} }
fun setTrackingCount(trackCount: Int) { fun setTrackingCount(trackCount: Int) {
this.trackCount = trackCount this.trackCount = trackCount
update()
notifyDataSetChanged()
} }
private fun updateCoverPosition() { private fun updateCoverPosition() {