Merge branch 'master' of https://github.com/gedoor/legado into master

pull/399/head
Robot 4 years ago
commit b6d2cf43f8
  1. 146
      app/src/main/java/io/legado/app/base/adapter/CommonRecyclerAdapter.kt
  2. 4
      app/src/main/java/io/legado/app/service/DownloadService.kt

@ -15,67 +15,67 @@ import java.util.*
* *
* 通用的adapter 可添加headerfooter以及不同类型item * 通用的adapter 可添加headerfooter以及不同类型item
*/ */
abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context): abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context) :
RecyclerView.Adapter<ItemViewHolder>() { RecyclerView.Adapter<ItemViewHolder>() {
constructor(context: Context, vararg delegates: ItemViewDelegate<ITEM>): this(context) { constructor(context: Context, vararg delegates: ItemViewDelegate<ITEM>) : this(context) {
addItemViewDelegates(*delegates) addItemViewDelegates(*delegates)
} }
constructor( constructor(
context: Context, context: Context,
vararg delegates: Pair<Int, ItemViewDelegate<ITEM>> vararg delegates: Pair<Int, ItemViewDelegate<ITEM>>
): this(context) { ) : this(context) {
addItemViewDelegates(*delegates) addItemViewDelegates(*delegates)
} }
private val inflater: LayoutInflater = LayoutInflater.from(context) private val inflater: LayoutInflater = LayoutInflater.from(context)
private var headerItems: SparseArray<View>? = null private var headerItems: SparseArray<View>? = null
private var footerItems: SparseArray<View>? = null private var footerItems: SparseArray<View>? = null
private val itemDelegates: HashMap<Int, ItemViewDelegate<ITEM>> = hashMapOf() private val itemDelegates: HashMap<Int, ItemViewDelegate<ITEM>> = hashMapOf()
private val items: MutableList<ITEM> = mutableListOf() private val items: MutableList<ITEM> = mutableListOf()
private val lock = Object() private val lock = Object()
private var itemClickListener: ((holder: ItemViewHolder, item: ITEM) -> Unit)? = null private var itemClickListener: ((holder: ItemViewHolder, item: ITEM) -> Unit)? = null
private var itemLongClickListener: ((holder: ItemViewHolder, item: ITEM) -> Boolean)? = null private var itemLongClickListener: ((holder: ItemViewHolder, item: ITEM) -> Boolean)? = null
// 这个用Kotlin的setter就行了, 不需要手动开一个函数进行设置 // 这个用Kotlin的setter就行了, 不需要手动开一个函数进行设置
var itemAnimation: ItemAnimation? = null var itemAnimation: ItemAnimation? = null
fun setOnItemClickListener(listener: (holder: ItemViewHolder, item: ITEM) -> Unit) { fun setOnItemClickListener(listener: (holder: ItemViewHolder, item: ITEM) -> Unit) {
itemClickListener = listener itemClickListener = listener
} }
fun setOnItemLongClickListener(listener: (holder: ItemViewHolder, item: ITEM) -> Boolean) { fun setOnItemLongClickListener(listener: (holder: ItemViewHolder, item: ITEM) -> Boolean) {
itemLongClickListener = listener itemLongClickListener = listener
} }
fun bindToRecyclerView(recyclerView: RecyclerView) { fun bindToRecyclerView(recyclerView: RecyclerView) {
recyclerView.adapter = this recyclerView.adapter = this
} }
fun <DELEGATE: ItemViewDelegate<ITEM>> addItemViewDelegate(viewType: Int, delegate: DELEGATE) { fun <DELEGATE : ItemViewDelegate<ITEM>> addItemViewDelegate(viewType: Int, delegate: DELEGATE) {
itemDelegates[viewType] = delegate itemDelegates[viewType] = delegate
} }
fun <DELEGATE: ItemViewDelegate<ITEM>> addItemViewDelegate(delegate: DELEGATE) { fun <DELEGATE : ItemViewDelegate<ITEM>> addItemViewDelegate(delegate: DELEGATE) {
itemDelegates[itemDelegates.size] = delegate itemDelegates[itemDelegates.size] = delegate
} }
fun <DELEGATE: ItemViewDelegate<ITEM>> addItemViewDelegates(vararg delegates: DELEGATE) { fun <DELEGATE : ItemViewDelegate<ITEM>> addItemViewDelegates(vararg delegates: DELEGATE) {
delegates.forEach { delegates.forEach {
addItemViewDelegate(it) addItemViewDelegate(it)
} }
} }
fun addItemViewDelegates(vararg delegates: Pair<Int, ItemViewDelegate<ITEM>>) = fun addItemViewDelegates(vararg delegates: Pair<Int, ItemViewDelegate<ITEM>>) =
delegates.forEach { delegates.forEach {
addItemViewDelegate(it.first, it.second) addItemViewDelegate(it.first, it.second)
} }
fun addHeaderView(header: View) { fun addHeaderView(header: View) {
synchronized(lock) { synchronized(lock) {
if (headerItems == null) { if (headerItems == null) {
@ -88,7 +88,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
} }
} }
} }
fun addFooterView(footer: View) = fun addFooterView(footer: View) =
synchronized(lock) { synchronized(lock) {
if (footerItems == null) { if (footerItems == null) {
@ -100,8 +100,8 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
notifyItemInserted(index) notifyItemInserted(index)
} }
} }
fun removeHeaderView(header: View) = fun removeHeaderView(header: View) =
synchronized(lock) { synchronized(lock) {
headerItems?.let { headerItems?.let {
@ -112,7 +112,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
} }
} }
} }
fun removeFooterView(footer: View) = fun removeFooterView(footer: View) =
synchronized(lock) { synchronized(lock) {
footerItems?.let { footerItems?.let {
@ -123,7 +123,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
} }
} }
} }
fun setItems(items: List<ITEM>?) { fun setItems(items: List<ITEM>?) {
synchronized(lock) { synchronized(lock) {
if (this.items.isNotEmpty()) { if (this.items.isNotEmpty()) {
@ -135,7 +135,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
notifyDataSetChanged() notifyDataSetChanged()
} }
} }
fun setItems(items: List<ITEM>?, diffResult: DiffUtil.DiffResult) { fun setItems(items: List<ITEM>?, diffResult: DiffUtil.DiffResult) {
synchronized(lock) { synchronized(lock) {
if (this.items.isNotEmpty()) { if (this.items.isNotEmpty()) {
@ -147,7 +147,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
diffResult.dispatchUpdatesTo(this) diffResult.dispatchUpdatesTo(this)
} }
} }
fun setItem(position: Int, item: ITEM) { fun setItem(position: Int, item: ITEM) {
synchronized(lock) { synchronized(lock) {
val oldSize = getActualItemCount() val oldSize = getActualItemCount()
@ -157,7 +157,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
} }
} }
} }
fun addItem(item: ITEM) { fun addItem(item: ITEM) {
synchronized(lock) { synchronized(lock) {
val oldSize = getActualItemCount() val oldSize = getActualItemCount()
@ -166,7 +166,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
} }
} }
} }
fun addItems(position: Int, newItems: List<ITEM>) { fun addItems(position: Int, newItems: List<ITEM>) {
synchronized(lock) { synchronized(lock) {
if (this.items.addAll(position, newItems)) { if (this.items.addAll(position, newItems)) {
@ -174,7 +174,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
} }
} }
} }
fun addItems(newItems: List<ITEM>) { fun addItems(newItems: List<ITEM>) {
synchronized(lock) { synchronized(lock) {
val oldSize = getActualItemCount() val oldSize = getActualItemCount()
@ -187,7 +187,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
} }
} }
} }
fun removeItem(position: Int) { fun removeItem(position: Int) {
synchronized(lock) { synchronized(lock) {
if (this.items.removeAt(position) != null) { if (this.items.removeAt(position) != null) {
@ -195,7 +195,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
} }
} }
} }
fun removeItem(item: ITEM) { fun removeItem(item: ITEM) {
synchronized(lock) { synchronized(lock) {
if (this.items.remove(item)) { if (this.items.remove(item)) {
@ -203,7 +203,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
} }
} }
} }
fun removeItems(items: List<ITEM>) { fun removeItems(items: List<ITEM>) {
synchronized(lock) { synchronized(lock) {
if (this.items.removeAll(items)) { if (this.items.removeAll(items)) {
@ -211,7 +211,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
} }
} }
} }
fun swapItem(oldPosition: Int, newPosition: Int) { fun swapItem(oldPosition: Int, newPosition: Int) {
synchronized(lock) { synchronized(lock) {
val size = getActualItemCount() val size = getActualItemCount()
@ -224,7 +224,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
} }
} }
} }
fun updateItem(item: ITEM) = fun updateItem(item: ITEM) =
synchronized(lock) { synchronized(lock) {
val index = this.items.indexOf(item) val index = this.items.indexOf(item)
@ -233,7 +233,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
notifyItemChanged(index) notifyItemChanged(index)
} }
} }
fun updateItem(position: Int, payload: Any) = fun updateItem(position: Int, payload: Any) =
synchronized(lock) { synchronized(lock) {
val size = getActualItemCount() val size = getActualItemCount()
@ -241,7 +241,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
notifyItemChanged(position + getHeaderCount(), payload) notifyItemChanged(position + getHeaderCount(), payload)
} }
} }
fun updateItems(fromPosition: Int, toPosition: Int, payloads: Any) = fun updateItems(fromPosition: Int, toPosition: Int, payloads: Any) =
synchronized(lock) { synchronized(lock) {
val size = getActualItemCount() val size = getActualItemCount()
@ -253,43 +253,43 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
) )
} }
} }
fun clearItems() = fun clearItems() =
synchronized(lock) { synchronized(lock) {
this.items.clear() this.items.clear()
notifyDataSetChanged() notifyDataSetChanged()
} }
fun isEmpty() = items.isEmpty() fun isEmpty() = items.isEmpty()
fun isNotEmpty() = items.isNotEmpty() fun isNotEmpty() = items.isNotEmpty()
/** /**
* 除去header和footer * 除去header和footer
*/ */
fun getActualItemCount() = items.size fun getActualItemCount() = items.size
fun getHeaderCount() = headerItems?.size() ?: 0 fun getHeaderCount() = headerItems?.size() ?: 0
fun getFooterCount() = footerItems?.size() ?: 0 fun getFooterCount() = footerItems?.size() ?: 0
fun getItem(position: Int): ITEM? = items.getOrNull(position) fun getItem(position: Int): ITEM? = items.getOrNull(position)
fun getItemByLayoutPosition(position: Int) = items.getOrNull(position - getHeaderCount()) fun getItemByLayoutPosition(position: Int) = items.getOrNull(position - getHeaderCount())
fun getItems(): List<ITEM> = items fun getItems(): List<ITEM> = items
protected open fun getItemViewType(item: ITEM, position: Int) = 0 protected open fun getItemViewType(item: ITEM, position: Int) = 0
/** /**
* grid 模式下使用 * grid 模式下使用
*/ */
protected open fun getSpanSize(item: ITEM, viewType: Int, position: Int) = 1 protected open fun getSpanSize(item: ITEM, viewType: Int, position: Int) = 1
final override fun getItemCount() = getActualItemCount() + getHeaderCount() + getFooterCount() final override fun getItemCount() = getActualItemCount() + getHeaderCount() + getFooterCount()
final override fun getItemViewType(position: Int) = when { final override fun getItemViewType(position: Int) = when {
isHeader(position) -> TYPE_HEADER_VIEW + position isHeader(position) -> TYPE_HEADER_VIEW + position
isFooter(position) -> TYPE_FOOTER_VIEW + position - getActualItemCount() - getHeaderCount() isFooter(position) -> TYPE_FOOTER_VIEW + position - getActualItemCount() - getHeaderCount()
@ -297,16 +297,16 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
getItemViewType(it, getActualPosition(position)) getItemViewType(it, getActualPosition(position))
} ?: 0 } ?: 0
} }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = when { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = when {
viewType < TYPE_HEADER_VIEW + getHeaderCount() -> { viewType < TYPE_HEADER_VIEW + getHeaderCount() -> {
ItemViewHolder(headerItems!!.get(viewType)) ItemViewHolder(headerItems!!.get(viewType))
} }
viewType >= TYPE_FOOTER_VIEW -> { viewType >= TYPE_FOOTER_VIEW -> {
ItemViewHolder(footerItems!!.get(viewType)) ItemViewHolder(footerItems!!.get(viewType))
} }
else -> { else -> {
val holder = ItemViewHolder( val holder = ItemViewHolder(
inflater.inflate( inflater.inflate(
@ -315,10 +315,10 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
false false
) )
) )
itemDelegates.getValue(viewType) itemDelegates.getValue(viewType)
.registerListener(holder) .registerListener(holder)
if (itemClickListener != null) { if (itemClickListener != null) {
holder.itemView.setOnClickListener { holder.itemView.setOnClickListener {
getItem(holder.layoutPosition)?.let { getItem(holder.layoutPosition)?.let {
@ -326,7 +326,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
} }
} }
} }
if (itemLongClickListener != null) { if (itemLongClickListener != null) {
holder.itemView.setOnLongClickListener { holder.itemView.setOnLongClickListener {
getItem(holder.layoutPosition)?.let { getItem(holder.layoutPosition)?.let {
@ -334,13 +334,13 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
} ?: true } ?: true
} }
} }
holder holder
} }
} }
final override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {} final override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {}
final override fun onBindViewHolder( final override fun onBindViewHolder(
holder: ItemViewHolder, holder: ItemViewHolder,
position: Int, position: Int,
@ -353,19 +353,19 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
} }
} }
} }
override fun onViewAttachedToWindow(holder: ItemViewHolder) { override fun onViewAttachedToWindow(holder: ItemViewHolder) {
super.onViewAttachedToWindow(holder) super.onViewAttachedToWindow(holder)
if (!isHeader(holder.layoutPosition) && !isFooter(holder.layoutPosition)) { if (!isHeader(holder.layoutPosition) && !isFooter(holder.layoutPosition)) {
addAnimation(holder) addAnimation(holder)
} }
} }
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) { override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
super.onAttachedToRecyclerView(recyclerView) super.onAttachedToRecyclerView(recyclerView)
val manager = recyclerView.layoutManager val manager = recyclerView.layoutManager
if (manager is GridLayoutManager) { if (manager is GridLayoutManager) {
manager.spanSizeLookup = object: GridLayoutManager.SpanSizeLookup() { manager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int { override fun getSpanSize(position: Int): Int {
return getItem(position)?.let { return getItem(position)?.let {
if (isHeader(position) || isFooter(position)) manager.spanCount else getSpanSize( if (isHeader(position) || isFooter(position)) manager.spanCount else getSpanSize(
@ -376,13 +376,13 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
} }
} }
} }
private fun isHeader(position: Int) = position < getHeaderCount() private fun isHeader(position: Int) = position < getHeaderCount()
private fun isFooter(position: Int) = position >= getActualItemCount() + getHeaderCount() private fun isFooter(position: Int) = position >= getActualItemCount() + getHeaderCount()
private fun getActualPosition(position: Int) = position - getHeaderCount() private fun getActualPosition(position: Int) = position - getHeaderCount()
private fun addAnimation(holder: ItemViewHolder) { private fun addAnimation(holder: ItemViewHolder) {
itemAnimation?.let { itemAnimation?.let {
if (it.itemAnimEnabled) { if (it.itemAnimEnabled) {
@ -393,7 +393,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
} }
} }
} }
protected open fun startAnimation(holder: ItemViewHolder, item: ItemAnimation) { protected open fun startAnimation(holder: ItemViewHolder, item: ItemAnimation) {
item.itemAnimation?.let { item.itemAnimation?.let {
for (anim in it.getAnimators(holder.itemView)) { for (anim in it.getAnimators(holder.itemView)) {
@ -402,12 +402,12 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
} }
} }
} }
companion object { companion object {
private const val TYPE_HEADER_VIEW = Int.MIN_VALUE private const val TYPE_HEADER_VIEW = Int.MIN_VALUE
private const val TYPE_FOOTER_VIEW = Int.MAX_VALUE - 999 private const val TYPE_FOOTER_VIEW = Int.MAX_VALUE - 999
} }
} }

@ -69,9 +69,7 @@ class DownloadService : BaseService() {
IntentAction.stop -> { IntentAction.stop -> {
val downloadId = intent.getLongExtra("downloadId", 0) val downloadId = intent.getLongExtra("downloadId", 0)
downloads.remove(downloadId) downloads.remove(downloadId)
if (downloads.isEmpty()) { stopSelf()
stopSelf()
}
} }
} }
return super.onStartCommand(intent, flags, startId) return super.onStartCommand(intent, flags, startId)

Loading…
Cancel
Save