From 5c06f7e2205d8dd4e0d9e4a5ea436c300e9ff8d4 Mon Sep 17 00:00:00 2001 From: gedoor Date: Tue, 15 Dec 2020 19:29:00 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/base/adapter/CommonRecyclerAdapter.kt | 165 +++++------ .../app/base/adapter/ItemViewDelegate.kt | 31 -- .../app/base/adapter/SimpleRecyclerAdapter.kt | 264 +++++++++++++++++- .../legado/app/ui/book/cache/CacheActivity.kt | 4 +- .../app/ui/book/explore/ExploreShowAdapter.kt | 4 +- .../app/ui/book/read/config/BgAdapter.kt | 4 +- .../ui/book/read/config/ReadStyleDialog.kt | 4 +- .../ui/book/read/config/SpeakEngineDialog.kt | 2 +- .../searchContent/SearchContentActivity.kt | 2 +- .../book/source/manage/BookSourceActivity.kt | 2 +- .../app/ui/book/toc/ChapterListFragment.kt | 2 +- .../ui/main/bookshelf/books/BooksFragment.kt | 2 +- .../app/ui/main/explore/ExploreAdapter.kt | 2 +- .../io/legado/app/ui/main/rss/RssAdapter.kt | 4 +- .../app/ui/replace/ReplaceRuleActivity.kt | 2 +- .../ui/rss/article/BaseRssArticlesAdapter.kt | 4 +- .../ui/rss/source/manage/RssSourceActivity.kt | 2 +- 17 files changed, 345 insertions(+), 155 deletions(-) delete mode 100644 app/src/main/java/io/legado/app/base/adapter/ItemViewDelegate.kt diff --git a/app/src/main/java/io/legado/app/base/adapter/CommonRecyclerAdapter.kt b/app/src/main/java/io/legado/app/base/adapter/CommonRecyclerAdapter.kt index 96de8207e..a22c15bfe 100644 --- a/app/src/main/java/io/legado/app/base/adapter/CommonRecyclerAdapter.kt +++ b/app/src/main/java/io/legado/app/base/adapter/CommonRecyclerAdapter.kt @@ -4,13 +4,11 @@ import android.content.Context import android.util.SparseArray import android.view.LayoutInflater import android.view.ViewGroup -import androidx.recyclerview.widget.AsyncListDiffer import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.viewbinding.ViewBinding import java.util.* -import kotlin.collections.ArrayList /** * Created by Invincible on 2017/11/24. @@ -21,27 +19,12 @@ import kotlin.collections.ArrayList abstract class CommonRecyclerAdapter(protected val context: Context) : RecyclerView.Adapter() { - constructor(context: Context, vararg delegates: ItemViewDelegate) : this(context) { - addItemViewDelegates(*delegates) - } - - constructor( - context: Context, - vararg delegates: Pair> - ) : this(context) { - addItemViewDelegates(*delegates) - } - val inflater: LayoutInflater = LayoutInflater.from(context) private val headerItems: SparseArray<(parent: ViewGroup) -> ViewBinding> by lazy { SparseArray() } private val footerItems: SparseArray<(parent: ViewGroup) -> ViewBinding> by lazy { SparseArray() } - private val itemDelegates: HashMap> = hashMapOf() - - private val asyncListDiffer: AsyncListDiffer by lazy { - AsyncListDiffer(this, diffItemCallback) - } + private val items: MutableList = mutableListOf() private val lock = Object() @@ -50,19 +33,6 @@ abstract class CommonRecyclerAdapter(protected val conte var itemAnimation: ItemAnimation? = null - open val diffItemCallback: DiffUtil.ItemCallback = - object : DiffUtil.ItemCallback() { - - override fun areItemsTheSame(oldItem: ITEM, newItem: ITEM): Boolean { - return oldItem == newItem - } - - override fun areContentsTheSame(oldItem: ITEM, newItem: ITEM): Boolean { - return true - } - - } - fun setOnItemClickListener(listener: (holder: ItemViewHolder, item: ITEM) -> Unit) { itemClickListener = listener } @@ -75,28 +45,6 @@ abstract class CommonRecyclerAdapter(protected val conte recyclerView.adapter = this } - fun > addItemViewDelegate( - viewType: Int, - delegate: DELEGATE - ) { - itemDelegates[viewType] = delegate - } - - fun addItemViewDelegate(delegate: ItemViewDelegate) { - itemDelegates[itemDelegates.size] = delegate - } - - fun addItemViewDelegates(vararg delegates: ItemViewDelegate) { - delegates.forEach { - addItemViewDelegate(it) - } - } - - fun addItemViewDelegates(vararg delegates: Pair>) = - delegates.forEach { - addItemViewDelegate(it.first, it.second) - } - fun addHeaderView(header: ((parent: ViewGroup) -> ViewBinding)) { synchronized(lock) { val index = headerItems.size() @@ -133,65 +81,88 @@ abstract class CommonRecyclerAdapter(protected val conte fun setItems(items: List?) { synchronized(lock) { - asyncListDiffer.submitList(items) + if (this.items.isNotEmpty()) { + this.items.clear() + } + if (items != null) { + this.items.addAll(items) + } + notifyDataSetChanged() + } + } + + fun setItems(items: List?, diffResult: DiffUtil.DiffResult) { + synchronized(lock) { + if (this.items.isNotEmpty()) { + this.items.clear() + } + if (items != null) { + this.items.addAll(items) + } + diffResult.dispatchUpdatesTo(this) } } fun setItem(position: Int, item: ITEM) { synchronized(lock) { - val list = ArrayList(asyncListDiffer.currentList) - list[position] = item - asyncListDiffer.submitList(list) + val oldSize = getActualItemCount() + if (position in 0 until oldSize) { + this.items[position] = item + notifyItemChanged(position + getHeaderCount()) + } } } fun addItem(item: ITEM) { synchronized(lock) { - val list = ArrayList(asyncListDiffer.currentList) - list.add(item) - asyncListDiffer.submitList(list) + val oldSize = getActualItemCount() + if (this.items.add(item)) { + notifyItemInserted(oldSize + getHeaderCount()) + } } } fun addItems(position: Int, newItems: List) { synchronized(lock) { - val list = ArrayList(asyncListDiffer.currentList) - list.addAll(position, newItems) - asyncListDiffer.submitList(list) + if (this.items.addAll(position, newItems)) { + notifyItemRangeInserted(position + getHeaderCount(), newItems.size) + } } } fun addItems(newItems: List) { synchronized(lock) { - val list = ArrayList(asyncListDiffer.currentList) - list.addAll(newItems) - asyncListDiffer.submitList(list) + val oldSize = getActualItemCount() + if (this.items.addAll(newItems)) { + if (oldSize == 0 && getHeaderCount() == 0) { + notifyDataSetChanged() + } else { + notifyItemRangeInserted(oldSize + getHeaderCount(), newItems.size) + } + } } } fun removeItem(position: Int) { synchronized(lock) { - val list = ArrayList(asyncListDiffer.currentList) - if (list.removeAt(position) != null) { - asyncListDiffer.submitList(list) + if (this.items.removeAt(position) != null) { + notifyItemRemoved(position + getHeaderCount()) } } } fun removeItem(item: ITEM) { synchronized(lock) { - val list = ArrayList(asyncListDiffer.currentList) - if (list.remove(item)) { - asyncListDiffer.submitList(list) + if (this.items.remove(item)) { + notifyItemRemoved(this.items.indexOf(item) + getHeaderCount()) } } } fun removeItems(items: List) { synchronized(lock) { - val list = ArrayList(asyncListDiffer.currentList) - if (list.removeAll(items)) { - asyncListDiffer.submitList(list) + if (this.items.removeAll(items)) { + notifyDataSetChanged() } } } @@ -202,7 +173,7 @@ abstract class CommonRecyclerAdapter(protected val conte if (oldPosition in 0 until size && newPosition in 0 until size) { val srcPosition = oldPosition + getHeaderCount() val targetPosition = newPosition + getHeaderCount() - Collections.swap(asyncListDiffer.currentList, srcPosition, targetPosition) + Collections.swap(this.items, srcPosition, targetPosition) notifyItemChanged(srcPosition) notifyItemChanged(targetPosition) } @@ -211,9 +182,9 @@ abstract class CommonRecyclerAdapter(protected val conte fun updateItem(item: ITEM) = synchronized(lock) { - val index = asyncListDiffer.currentList.indexOf(item) + val index = this.items.indexOf(item) if (index >= 0) { - asyncListDiffer.currentList[index] = item + this.items[index] = item notifyItemChanged(index) } } @@ -240,17 +211,18 @@ abstract class CommonRecyclerAdapter(protected val conte fun clearItems() = synchronized(lock) { - asyncListDiffer.submitList(arrayListOf()) + this.items.clear() + notifyDataSetChanged() } - fun isEmpty() = asyncListDiffer.currentList.isEmpty() + fun isEmpty() = items.isEmpty() - fun isNotEmpty() = asyncListDiffer.currentList.isNotEmpty() + fun isNotEmpty() = items.isNotEmpty() /** * 除去header和footer */ - fun getActualItemCount() = asyncListDiffer.currentList.size + fun getActualItemCount() = items.size fun getHeaderCount() = headerItems.size() @@ -258,12 +230,11 @@ abstract class CommonRecyclerAdapter(protected val conte fun getFooterCount() = footerItems.size() - fun getItem(position: Int): ITEM? = asyncListDiffer.currentList.getOrNull(position) + fun getItem(position: Int): ITEM? = items.getOrNull(position) - fun getItemByLayoutPosition(position: Int) = - asyncListDiffer.currentList.getOrNull(position - getHeaderCount()) + fun getItemByLayoutPosition(position: Int) = items.getOrNull(position - getHeaderCount()) - fun getItems(): List = asyncListDiffer.currentList + fun getItems(): List = items protected open fun getItemViewType(item: ITEM, position: Int) = 0 @@ -295,8 +266,7 @@ abstract class CommonRecyclerAdapter(protected val conte val holder = ItemViewHolder(getViewBinding(parent)) @Suppress("UNCHECKED_CAST") - itemDelegates.getValue(viewType) - .registerListener(holder, (holder.binding as VB)) + registerListener(holder, (holder.binding as VB)) if (itemClickListener != null) { holder.itemView.setOnClickListener { @@ -330,8 +300,7 @@ abstract class CommonRecyclerAdapter(protected val conte ) { if (!isHeader(holder.layoutPosition) && !isFooter(holder.layoutPosition)) { getItem(holder.layoutPosition - getHeaderCount())?.let { - itemDelegates.getValue(getItemViewType(holder.layoutPosition)) - .convert(holder, (holder.binding as VB), it, payloads) + convert(holder, (holder.binding as VB), it, payloads) } } } @@ -381,6 +350,22 @@ abstract class CommonRecyclerAdapter(protected val conte } } + /** + * 如果使用了事件回调,回调里不要直接使用item,会出现不更新的问题, + * 使用getItem(holder.layoutPosition)来获取item + */ + abstract fun convert( + holder: ItemViewHolder, + binding: VB, + item: ITEM, + payloads: MutableList + ) + + /** + * 注册事件 + */ + abstract fun registerListener(holder: ItemViewHolder, binding: VB) + companion object { private const val TYPE_HEADER_VIEW = Int.MIN_VALUE private const val TYPE_FOOTER_VIEW = Int.MAX_VALUE - 999 diff --git a/app/src/main/java/io/legado/app/base/adapter/ItemViewDelegate.kt b/app/src/main/java/io/legado/app/base/adapter/ItemViewDelegate.kt deleted file mode 100644 index d5d4d947c..000000000 --- a/app/src/main/java/io/legado/app/base/adapter/ItemViewDelegate.kt +++ /dev/null @@ -1,31 +0,0 @@ -package io.legado.app.base.adapter - -import android.content.Context -import androidx.viewbinding.ViewBinding - -/** - * Created by Invincible on 2017/11/24. - * - * item代理, - */ -abstract class ItemViewDelegate(protected val context: Context) { - - /** - * 如果使用了事件回调,回调里不要直接使用item,会出现不更新的问题, - * 使用getItem(holder.layoutPosition)来获取item, - * 或者使用registerListener(holder: ItemViewHolder, position: Int) - */ - abstract fun convert( - holder: ItemViewHolder, - binding: VB, - item: ITEM, - payloads: MutableList - ) - - - /** - * 注册事件 - */ - abstract fun registerListener(holder: ItemViewHolder, binding: VB) - -} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/base/adapter/SimpleRecyclerAdapter.kt b/app/src/main/java/io/legado/app/base/adapter/SimpleRecyclerAdapter.kt index 9d8b7a259..547abb1b6 100644 --- a/app/src/main/java/io/legado/app/base/adapter/SimpleRecyclerAdapter.kt +++ b/app/src/main/java/io/legado/app/base/adapter/SimpleRecyclerAdapter.kt @@ -1,30 +1,265 @@ package io.legado.app.base.adapter import android.content.Context +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.AsyncListDiffer +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.RecyclerView import androidx.viewbinding.ViewBinding +import java.util.* +import kotlin.collections.ArrayList /** * Created by Invincible on 2017/12/15. */ -abstract class SimpleRecyclerAdapter(context: Context) : - CommonRecyclerAdapter(context) { +@Suppress("unused") +abstract class SimpleRecyclerAdapter(protected val context: Context) : + RecyclerView.Adapter() { - init { - addItemViewDelegate(object : ItemViewDelegate(context) { + val inflater: LayoutInflater = LayoutInflater.from(context) - override fun convert( - holder: ItemViewHolder, - binding: VB, - item: ITEM, - payloads: MutableList - ) { - this@SimpleRecyclerAdapter.convert(holder, binding, item, payloads) + private val asyncListDiffer: AsyncListDiffer by lazy { + AsyncListDiffer(this, diffItemCallback) + } + + private val lock = Object() + + private var itemClickListener: ((holder: ItemViewHolder, item: ITEM) -> Unit)? = null + private var itemLongClickListener: ((holder: ItemViewHolder, item: ITEM) -> Boolean)? = null + + var itemAnimation: ItemAnimation? = null + + open val diffItemCallback: DiffUtil.ItemCallback = + object : DiffUtil.ItemCallback() { + + override fun areItemsTheSame(oldItem: ITEM, newItem: ITEM): Boolean { + return oldItem == newItem } - override fun registerListener(holder: ItemViewHolder, binding: VB) { - this@SimpleRecyclerAdapter.registerListener(holder, binding) + override fun areContentsTheSame(oldItem: ITEM, newItem: ITEM): Boolean { + return true } - }) + + } + + fun setOnItemClickListener(listener: (holder: ItemViewHolder, item: ITEM) -> Unit) { + itemClickListener = listener + } + + fun setOnItemLongClickListener(listener: (holder: ItemViewHolder, item: ITEM) -> Boolean) { + itemLongClickListener = listener + } + + fun bindToRecyclerView(recyclerView: RecyclerView) { + recyclerView.adapter = this + } + + fun setItems(items: List?) { + synchronized(lock) { + asyncListDiffer.submitList(items) + } + } + + fun setItem(position: Int, item: ITEM) { + synchronized(lock) { + val list = ArrayList(asyncListDiffer.currentList) + list[position] = item + asyncListDiffer.submitList(list) + } + } + + fun addItem(item: ITEM) { + synchronized(lock) { + val list = ArrayList(asyncListDiffer.currentList) + list.add(item) + asyncListDiffer.submitList(list) + } + } + + fun addItems(position: Int, newItems: List) { + synchronized(lock) { + val list = ArrayList(asyncListDiffer.currentList) + list.addAll(position, newItems) + asyncListDiffer.submitList(list) + } + } + + fun addItems(newItems: List) { + synchronized(lock) { + val list = ArrayList(asyncListDiffer.currentList) + list.addAll(newItems) + asyncListDiffer.submitList(list) + } + } + + fun removeItem(position: Int) { + synchronized(lock) { + val list = ArrayList(asyncListDiffer.currentList) + if (list.removeAt(position) != null) { + asyncListDiffer.submitList(list) + } + } + } + + fun removeItem(item: ITEM) { + synchronized(lock) { + val list = ArrayList(asyncListDiffer.currentList) + if (list.remove(item)) { + asyncListDiffer.submitList(list) + } + } + } + + fun removeItems(items: List) { + synchronized(lock) { + val list = ArrayList(asyncListDiffer.currentList) + if (list.removeAll(items)) { + asyncListDiffer.submitList(list) + } + } + } + + fun swapItem(oldPosition: Int, newPosition: Int) { + synchronized(lock) { + val size = itemCount + if (oldPosition in 0 until size && newPosition in 0 until size) { + Collections.swap(asyncListDiffer.currentList, oldPosition, newPosition) + notifyItemChanged(oldPosition) + notifyItemChanged(newPosition) + } + } + } + + fun updateItem(item: ITEM) = + synchronized(lock) { + val index = asyncListDiffer.currentList.indexOf(item) + if (index >= 0) { + asyncListDiffer.currentList[index] = item + notifyItemChanged(index) + } + } + + fun updateItem(position: Int, payload: Any) = + synchronized(lock) { + val size = itemCount + if (position in 0 until size) { + notifyItemChanged(position, payload) + } + } + + fun updateItems(fromPosition: Int, toPosition: Int, payloads: Any) = + synchronized(lock) { + val size = itemCount + if (fromPosition in 0 until size && toPosition in 0 until size) { + notifyItemRangeChanged( + fromPosition, + toPosition - fromPosition + 1, + payloads + ) + } + } + + fun clearItems() = + synchronized(lock) { + asyncListDiffer.submitList(arrayListOf()) + } + + fun isEmpty() = asyncListDiffer.currentList.isEmpty() + + fun isNotEmpty() = asyncListDiffer.currentList.isNotEmpty() + + fun getItem(position: Int): ITEM? = asyncListDiffer.currentList.getOrNull(position) + + fun getItems(): List = asyncListDiffer.currentList + + /** + * grid 模式下使用 + */ + protected open fun getSpanSize(viewType: Int, position: Int) = 1 + + final override fun getItemCount() = getItems().size + + final override fun getItemViewType(position: Int): Int { + return 0 + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val holder = ItemViewHolder(getViewBinding(parent)) + + @Suppress("UNCHECKED_CAST") + registerListener(holder, (holder.binding as VB)) + + if (itemClickListener != null) { + holder.itemView.setOnClickListener { + getItem(holder.layoutPosition)?.let { + itemClickListener?.invoke(holder, it) + } + } + } + + if (itemLongClickListener != null) { + holder.itemView.setOnLongClickListener { + getItem(holder.layoutPosition)?.let { + itemLongClickListener?.invoke(holder, it) ?: true + } ?: true + } + } + + return holder + } + + protected abstract fun getViewBinding(parent: ViewGroup): VB + + final override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {} + + @Suppress("UNCHECKED_CAST") + final override fun onBindViewHolder( + holder: ItemViewHolder, + position: Int, + payloads: MutableList + ) { + getItem(holder.layoutPosition)?.let { + convert(holder, (holder.binding as VB), it, payloads) + } + } + + override fun onViewAttachedToWindow(holder: ItemViewHolder) { + super.onViewAttachedToWindow(holder) + addAnimation(holder) + } + + override fun onAttachedToRecyclerView(recyclerView: RecyclerView) { + super.onAttachedToRecyclerView(recyclerView) + val manager = recyclerView.layoutManager + if (manager is GridLayoutManager) { + manager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() { + override fun getSpanSize(position: Int): Int { + return getSpanSize(getItemViewType(position), position) + } + } + } + } + + private fun addAnimation(holder: ItemViewHolder) { + itemAnimation?.let { + if (it.itemAnimEnabled) { + if (!it.itemAnimFirstOnly || holder.layoutPosition > it.itemAnimStartPosition) { + startAnimation(holder, it) + it.itemAnimStartPosition = holder.layoutPosition + } + } + } + } + + protected open fun startAnimation(holder: ItemViewHolder, item: ItemAnimation) { + item.itemAnimation?.let { + for (anim in it.getAnimators(holder.itemView)) { + anim.setDuration(item.itemAnimDuration).start() + anim.interpolator = item.itemAnimInterpolator + } + } } /** @@ -42,4 +277,5 @@ abstract class SimpleRecyclerAdapter(context: Context) : * 注册事件 */ abstract fun registerListener(holder: ItemViewHolder, binding: VB) + } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/book/cache/CacheActivity.kt b/app/src/main/java/io/legado/app/ui/book/cache/CacheActivity.kt index 74f4164fe..efad70917 100644 --- a/app/src/main/java/io/legado/app/ui/book/cache/CacheActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/cache/CacheActivity.kt @@ -163,7 +163,7 @@ class CacheActivity : VMBaseActivity() } adapter.cacheChapters[book.bookUrl] = chapterCaches withContext(Dispatchers.Main) { - adapter.notifyItemRangeChanged(0, adapter.getActualItemCount(), true) + adapter.notifyItemRangeChanged(0, adapter.itemCount, true) } } } @@ -179,7 +179,7 @@ class CacheActivity : VMBaseActivity() menu?.applyTint(this) } adapter.downloadMap = it - adapter.notifyItemRangeChanged(0, adapter.getActualItemCount(), true) + adapter.notifyItemRangeChanged(0, adapter.itemCount, true) } observeEvent(EventBus.SAVE_CONTENT) { adapter.cacheChapters[it.bookUrl]?.add(it.url) diff --git a/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowAdapter.kt b/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowAdapter.kt index 83e5908f9..45dccfd0b 100644 --- a/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowAdapter.kt @@ -3,8 +3,8 @@ package io.legado.app.ui.book.explore import android.content.Context import android.view.ViewGroup import io.legado.app.R +import io.legado.app.base.adapter.CommonRecyclerAdapter import io.legado.app.base.adapter.ItemViewHolder -import io.legado.app.base.adapter.SimpleRecyclerAdapter import io.legado.app.data.entities.Book import io.legado.app.data.entities.SearchBook import io.legado.app.databinding.ItemSearchBinding @@ -13,7 +13,7 @@ import io.legado.app.utils.visible import org.jetbrains.anko.sdk27.listeners.onClick class ExploreShowAdapter(context: Context, val callBack: CallBack) : - SimpleRecyclerAdapter(context) { + CommonRecyclerAdapter(context) { override fun getViewBinding(parent: ViewGroup): ItemSearchBinding { return ItemSearchBinding.inflate(inflater, parent, false) diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/BgAdapter.kt b/app/src/main/java/io/legado/app/ui/book/read/config/BgAdapter.kt index f65f6b852..135c66c1b 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/config/BgAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/config/BgAdapter.kt @@ -2,8 +2,8 @@ package io.legado.app.ui.book.read.config import android.content.Context import android.view.ViewGroup +import io.legado.app.base.adapter.CommonRecyclerAdapter import io.legado.app.base.adapter.ItemViewHolder -import io.legado.app.base.adapter.SimpleRecyclerAdapter import io.legado.app.constant.EventBus import io.legado.app.databinding.ItemBgImageBinding import io.legado.app.help.ImageLoader @@ -13,7 +13,7 @@ import org.jetbrains.anko.sdk27.listeners.onClick import java.io.File class BgAdapter(context: Context, val textColor: Int) : - SimpleRecyclerAdapter(context) { + CommonRecyclerAdapter(context) { override fun getViewBinding(parent: ViewGroup): ItemBgImageBinding { return ItemBgImageBinding.inflate(inflater, parent, false) diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/ReadStyleDialog.kt b/app/src/main/java/io/legado/app/ui/book/read/config/ReadStyleDialog.kt index 73df88356..1e93c1d48 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/config/ReadStyleDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/config/ReadStyleDialog.kt @@ -6,8 +6,8 @@ import android.view.* import androidx.core.view.get import io.legado.app.R import io.legado.app.base.BaseDialogFragment +import io.legado.app.base.adapter.CommonRecyclerAdapter import io.legado.app.base.adapter.ItemViewHolder -import io.legado.app.base.adapter.SimpleRecyclerAdapter import io.legado.app.constant.EventBus import io.legado.app.databinding.DialogReadBookStyleBinding import io.legado.app.databinding.ItemReadStyleBinding @@ -207,7 +207,7 @@ class ReadStyleDialog : BaseDialogFragment(), FontSelectDialog.CallBack { } inner class StyleAdapter : - SimpleRecyclerAdapter(requireContext()) { + CommonRecyclerAdapter(requireContext()) { override fun getViewBinding(parent: ViewGroup): ItemReadStyleBinding { return ItemReadStyleBinding.inflate(inflater, parent, false) 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 4b401dd55..43d09c391 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 @@ -151,7 +151,7 @@ class SpeakEngineDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener cbName.onClick { getItem(holder.layoutPosition)?.let { httpTTS -> engineId = httpTTS.id - notifyItemRangeChanged(0, getActualItemCount()) + notifyItemRangeChanged(0, itemCount) } } ivEdit.onClick { diff --git a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentActivity.kt b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentActivity.kt index 9b7d0c75b..a111a8cf2 100644 --- a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentActivity.kt @@ -117,7 +117,7 @@ class SearchContentActivity : launch(Dispatchers.IO) { adapter.cacheFileNames.addAll(BookHelp.getChapterFiles(book)) withContext(Dispatchers.Main) { - adapter.notifyItemRangeChanged(0, adapter.getActualItemCount(), true) + adapter.notifyItemRangeChanged(0, adapter.itemCount, true) } } } diff --git a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt index 5621e3b68..2296040d7 100644 --- a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt @@ -399,7 +399,7 @@ class BookSourceActivity : VMBaseActivity(R.layout.fragme launch(IO) { adapter.cacheFileNames.addAll(BookHelp.getChapterFiles(book)) withContext(Main) { - adapter.notifyItemRangeChanged(0, adapter.getActualItemCount(), true) + adapter.notifyItemRangeChanged(0, adapter.itemCount, true) } } } diff --git a/app/src/main/java/io/legado/app/ui/main/bookshelf/books/BooksFragment.kt b/app/src/main/java/io/legado/app/ui/main/bookshelf/books/BooksFragment.kt index 77de0cc75..6f0990a76 100644 --- a/app/src/main/java/io/legado/app/ui/main/bookshelf/books/BooksFragment.kt +++ b/app/src/main/java/io/legado/app/ui/main/bookshelf/books/BooksFragment.kt @@ -134,7 +134,7 @@ class BooksFragment : BaseFragment(R.layout.fragment_books), } fun getBooksCount(): Int { - return booksAdapter.getActualItemCount() + return booksAdapter.itemCount } override fun open(book: Book) { diff --git a/app/src/main/java/io/legado/app/ui/main/explore/ExploreAdapter.kt b/app/src/main/java/io/legado/app/ui/main/explore/ExploreAdapter.kt index c61701ad9..6532b63fb 100644 --- a/app/src/main/java/io/legado/app/ui/main/explore/ExploreAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/main/explore/ExploreAdapter.kt @@ -39,7 +39,7 @@ class ExploreAdapter(context: Context, private val scope: CoroutineScope, val ca payloads: MutableList ) { with(binding) { - if (holder.layoutPosition == getActualItemCount() - 1) { + if (holder.layoutPosition == itemCount - 1) { root.setPadding(16.dp, 12.dp, 16.dp, 12.dp) } else { root.setPadding(16.dp, 12.dp, 16.dp, 0) diff --git a/app/src/main/java/io/legado/app/ui/main/rss/RssAdapter.kt b/app/src/main/java/io/legado/app/ui/main/rss/RssAdapter.kt index 4d98ffb7d..9006f2e61 100644 --- a/app/src/main/java/io/legado/app/ui/main/rss/RssAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/main/rss/RssAdapter.kt @@ -5,8 +5,8 @@ import android.view.View import android.view.ViewGroup import androidx.appcompat.widget.PopupMenu import io.legado.app.R +import io.legado.app.base.adapter.CommonRecyclerAdapter import io.legado.app.base.adapter.ItemViewHolder -import io.legado.app.base.adapter.SimpleRecyclerAdapter import io.legado.app.data.entities.RssSource import io.legado.app.databinding.ItemRssBinding import io.legado.app.help.ImageLoader @@ -14,7 +14,7 @@ import org.jetbrains.anko.sdk27.listeners.onClick import org.jetbrains.anko.sdk27.listeners.onLongClick class RssAdapter(context: Context, val callBack: CallBack) : - SimpleRecyclerAdapter(context) { + CommonRecyclerAdapter(context) { override fun getViewBinding(parent: ViewGroup): ItemRssBinding { return ItemRssBinding.inflate(inflater, parent, false) 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 9bd05e999..100524b92 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 @@ -281,7 +281,7 @@ class ReplaceRuleActivity : VMBaseActivity(context: Context, val callBack: CallBack) : - SimpleRecyclerAdapter(context) { + CommonRecyclerAdapter(context) { interface CallBack { val isGridLayout: 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 94cfd3eb3..dd11955de 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 @@ -221,7 +221,7 @@ class RssSourceActivity : VMBaseActivity Date: Tue, 15 Dec 2020 19:40:27 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=90=8C=E6=AD=A5?= =?UTF-8?q?=E8=BF=9B=E5=BA=A6=E5=BC=80=E5=85=B3,=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E5=BC=80=E5=90=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/io/legado/app/constant/PreferKey.kt | 1 + .../main/java/io/legado/app/help/AppConfig.kt | 2 ++ .../io/legado/app/service/help/ReadBook.kt | 1 + .../app/ui/book/read/ReadBookViewModel.kt | 19 ++++++++++--------- app/src/main/res/values-zh-rHK/strings.xml | 2 ++ app/src/main/res/values-zh-rTW/strings.xml | 2 ++ app/src/main/res/values-zh/strings.xml | 2 ++ app/src/main/res/values/strings.xml | 2 ++ app/src/main/res/xml/pref_config_backup.xml | 9 +++++++++ 9 files changed, 31 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/io/legado/app/constant/PreferKey.kt b/app/src/main/java/io/legado/app/constant/PreferKey.kt index a69fd3368..9f055e498 100644 --- a/app/src/main/java/io/legado/app/constant/PreferKey.kt +++ b/app/src/main/java/io/legado/app/constant/PreferKey.kt @@ -63,6 +63,7 @@ object PreferKey { const val autoChangeSource = "autoChangeSource" const val importKeepName = "importKeepName" const val screenDirection = "screenDirection" + const val syncBookProgress = "syncBookProgress" const val cPrimary = "colorPrimary" const val cAccent = "colorAccent" diff --git a/app/src/main/java/io/legado/app/help/AppConfig.kt b/app/src/main/java/io/legado/app/help/AppConfig.kt index 2efcd482c..b96344abc 100644 --- a/app/src/main/java/io/legado/app/help/AppConfig.kt +++ b/app/src/main/java/io/legado/app/help/AppConfig.kt @@ -147,6 +147,8 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener { val importKeepName get() = context.getPrefBoolean(PreferKey.importKeepName) + val syncBookProgress get() = context.getPrefBoolean(PreferKey.syncBookProgress, true) + private fun getPrefUserAgent(): String { val ua = context.getPrefString(PreferKey.userAgent) if (ua.isNullOrBlank()) { diff --git a/app/src/main/java/io/legado/app/service/help/ReadBook.kt b/app/src/main/java/io/legado/app/service/help/ReadBook.kt index b4bf0e7e9..dd68512fd 100644 --- a/app/src/main/java/io/legado/app/service/help/ReadBook.kt +++ b/app/src/main/java/io/legado/app/service/help/ReadBook.kt @@ -91,6 +91,7 @@ object ReadBook { } fun uploadProgress() { + if (!AppConfig.syncBookProgress) return book?.let { BookWebDav.uploadBookProgress(it) } diff --git a/app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt b/app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt index 088fe98e1..b7801ae09 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt @@ -163,17 +163,18 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { } fun syncBookProgress(book: Book) { - execute { - BookWebDav.getBookProgress(book)?.let { progress -> - if (progress.durChapterIndex < book.durChapterIndex || - (progress.durChapterIndex == book.durChapterIndex && progress.durChapterPos < book.durChapterPos) - ) { - processLiveData.postValue(progress) - } else { - ReadBook.setProgress(progress) + if (!AppConfig.syncBookProgress) + execute { + BookWebDav.getBookProgress(book)?.let { progress -> + if (progress.durChapterIndex < book.durChapterIndex || + (progress.durChapterIndex == book.durChapterIndex && progress.durChapterPos < book.durChapterPos) + ) { + processLiveData.postValue(progress) + } else { + ReadBook.setProgress(progress) + } } } - } } fun changeTo(newBook: Book) { diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index 44d480018..9055d82d3 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -790,5 +790,7 @@ 添加大佬们提供的规则导入地址\n添加后点击可导入规则 拉取云端进度 当前进度超过云端进度,是否同步? + 同步阅读进度 + 进入退出阅读界面时同步阅读进度 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 71781981d..844c81fbd 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -791,5 +791,7 @@ 添加大佬们提供的规则导入地址\n添加后点击可导入规则 拉取云端进度 当前进度超过云端进度,是否同步? + 同步阅读进度 + 进入退出阅读界面时同步阅读进度 diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 4baf18b05..4ce861774 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -794,5 +794,7 @@ 添加大佬们提供的规则导入地址\n添加后点击可导入规则 拉取云端进度 当前进度超过云端进度,是否同步? + 同步阅读进度 + 进入退出阅读界面时同步阅读进度 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b28807641..e02fd21f0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -797,5 +797,7 @@ 添加大佬们提供的规则导入地址\n添加后点击可导入规则 拉取云端进度 当前进度超过云端进度,是否同步? + 同步阅读进度 + 进入退出阅读界面时同步阅读进度 diff --git a/app/src/main/res/xml/pref_config_backup.xml b/app/src/main/res/xml/pref_config_backup.xml index bc0c8adc7..fe51a816a 100644 --- a/app/src/main/res/xml/pref_config_backup.xml +++ b/app/src/main/res/xml/pref_config_backup.xml @@ -36,6 +36,15 @@ app:allowDividerBelow="false" app:iconSpaceReserved="false" /> + + Date: Tue, 15 Dec 2020 19:41:24 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=90=8C=E6=AD=A5?= =?UTF-8?q?=E8=BF=9B=E5=BA=A6=E5=BC=80=E5=85=B3,=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E5=BC=80=E5=90=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/assets/updateLog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md index ce115a174..8c1618ac4 100644 --- a/app/src/main/assets/updateLog.md +++ b/app/src/main/assets/updateLog.md @@ -6,6 +6,7 @@ **2020/12/15** * 修复一些引起崩溃的bug * 修复搜书和换源可能什么分组都没有的bug +* 添加同步进度开关,默认开启 **2020/12/14** * 修复bug