Skip to content

Commit

Permalink
[优化] RecyclerView 根据 Payload 进行局部更新。
Browse files Browse the repository at this point in the history
  • Loading branch information
YenalyLiew committed Mar 31, 2024
1 parent cc9af88 commit fb4dcd4
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,28 @@ data class VideoComments(

val realReplyId get() = post.foreignId ?: checkNotNull(id)
val realLikesCount get() = thumbUp
fun incrementLikesCount(cancel: Boolean = false) {
if (thumbUp != null) {
thumbUp = thumbUp!! + if (cancel) -1 else 1
post.likeCommentStatus = !cancel
post.unlikeCommentStatus = false
}
fun incrementLikesCount(cancel: Boolean = false): VideoComment {
return thumbUp?.let {
copy(
thumbUp = it + if (cancel) -1 else 1,
post = post.copy(
likeCommentStatus = !cancel,
unlikeCommentStatus = false
)
)
} ?: this
}

fun decrementLikesCount(cancel: Boolean = false) {
if (thumbUp != null) {
thumbUp = thumbUp!! - if (cancel) -1 else 1
post.likeCommentStatus = false
post.unlikeCommentStatus = !cancel
}
fun decrementLikesCount(cancel: Boolean = false): VideoComment {
return thumbUp?.let {
copy(
thumbUp = it - if (cancel) -1 else 1,
post = post.copy(
likeCommentStatus = false,
unlikeCommentStatus = !cancel
)
)
} ?: this
}

data class POST(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ class HanimeDownloadingRvAdapter(private val fragment: DownloadingFragment) :
}

companion object {
private const val DOWNLOADING = 1
private const val PAUSE = 1 shl 1

val COMPARATOR = object : DiffUtil.ItemCallback<HanimeDownloadEntity>() {
override fun areContentsTheSame(
oldItem: HanimeDownloadEntity,
Expand All @@ -62,6 +65,18 @@ class HanimeDownloadingRvAdapter(private val fragment: DownloadingFragment) :
): Boolean {
return oldItem.id == newItem.id
}

override fun getChangePayload(
oldItem: HanimeDownloadEntity,
newItem: HanimeDownloadEntity,
): Any {
var bitset = 0
if (oldItem.progress != newItem.progress || oldItem.downloadedLength != newItem.downloadedLength)
bitset = bitset or DOWNLOADING
if (oldItem.isDownloading != newItem.isDownloading)
bitset = bitset or PAUSE
return bitset
}
}
}

Expand All @@ -76,17 +91,40 @@ class HanimeDownloadingRvAdapter(private val fragment: DownloadingFragment) :
}
holder.binding.tvSize.text = spannable {
item.downloadedLength.formatFileSize().text()
" | ".span {
color(Color.RED)
}
" | ".span { color(Color.RED) }
item.length.formatFileSize().span { style(Typeface.BOLD) }
}
holder.binding.tvQuality.text = item.quality
holder.binding.tvProgress.text = "${item.progress}%"
holder.binding.pbProgress.setProgress(item.progress, false)
holder.binding.pbProgress.setProgress(item.progress, true)
holder.binding.btnStart.handleStartButton(item.isDownloading)
}

@SuppressLint("SetTextI18n")
override fun onBindViewHolder(
holder: ViewHolder,
position: Int,
item: HanimeDownloadEntity?,
payloads: List<Any>,
) {
if (payloads.isEmpty() || payloads.first() == 0)
return super.onBindViewHolder(holder, position, item, payloads)
item.notNull()
val bitset = payloads.first() as Int
if (bitset and DOWNLOADING != 0) {
holder.binding.tvSize.text = spannable {
item.downloadedLength.formatFileSize().text()
" | ".span { color(Color.RED) }
item.length.formatFileSize().span { style(Typeface.BOLD) }
}
holder.binding.tvProgress.text = "${item.progress}%"
holder.binding.pbProgress.setProgress(item.progress, true)
}
if (bitset and PAUSE != 0) {
holder.binding.btnStart.handleStartButton(item.isDownloading)
}
}

override fun onCreateViewHolder(
context: Context,
parent: ViewGroup,
Expand Down Expand Up @@ -137,7 +175,7 @@ class HanimeDownloadingRvAdapter(private val fragment: DownloadingFragment) :
}


fun MaterialButton.handleStartButton(isDownloading: Boolean) {
private fun MaterialButton.handleStartButton(isDownloading: Boolean) {
if (isDownloading) {
setText(R.string.pause)
setIconResource(R.drawable.ic_baseline_pause_24)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.appcompat.content.res.AppCompatResources
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
Expand All @@ -15,6 +14,7 @@ import coil.load
import coil.transform.CircleCropTransformation
import com.chad.library.adapter4.BaseDifferAdapter
import com.chad.library.adapter4.viewholder.DataBindingHolder
import com.google.android.material.button.MaterialButton
import com.itxca.spannablex.spannable
import com.lxj.xpopup.XPopup
import com.yenaly.han1meviewer.COMMENT_ID
Expand Down Expand Up @@ -45,6 +45,8 @@ class VideoCommentRvAdapter(private val fragment: Fragment? = null) :
var replyPopup: ReplyPopup? = null

companion object {
private const val THUMB = 0

val COMPARATOR = object : DiffUtil.ItemCallback<VideoComments.VideoComment>() {
override fun areItemsTheSame(
oldItem: VideoComments.VideoComment,
Expand All @@ -59,6 +61,15 @@ class VideoCommentRvAdapter(private val fragment: Fragment? = null) :
): Boolean {
return oldItem == newItem
}

override fun getChangePayload(
oldItem: VideoComments.VideoComment,
newItem: VideoComments.VideoComment,
): Any? {
return if (oldItem.post.likeCommentStatus != newItem.post.likeCommentStatus ||
oldItem.post.unlikeCommentStatus != newItem.post.unlikeCommentStatus
) THUMB else null
}
}
}

Expand All @@ -82,16 +93,23 @@ class VideoCommentRvAdapter(private val fragment: Fragment? = null) :
holder.binding.tvDate.text = item.date
holder.binding.tvUsername.text = item.username
holder.binding.btnViewMoreReplies.isVisible = item.hasMoreReplies
holder.binding.btnThumbUp.text = item.realLikesCount.toString()
holder.binding.btnThumbUp.icon = if (item.post.likeCommentStatus) {
AppCompatResources.getDrawable(context, R.drawable.ic_baseline_thumb_up_alt_24)
} else {
AppCompatResources.getDrawable(context, R.drawable.ic_baseline_thumb_up_off_alt_24)
}
holder.binding.btnThumbDown.icon = if (item.post.unlikeCommentStatus) {
AppCompatResources.getDrawable(context, R.drawable.ic_baseline_thumb_down_alt_24)
} else {
AppCompatResources.getDrawable(context, R.drawable.ic_baseline_thumb_down_off_alt_24)
holder.binding.btnThumbUp.text = item.realLikesCount?.toString()
holder.binding.btnThumbUp.setThumbUpIcon(item.post.likeCommentStatus)
holder.binding.btnThumbDown.setThumbDownIcon(item.post.unlikeCommentStatus)
}

override fun onBindViewHolder(
holder: ViewHolder,
position: Int,
item: VideoComments.VideoComment?,
payloads: List<Any>,
) {
if (payloads.isEmpty()) return super.onBindViewHolder(holder, position, item, payloads)
item.notNull()
if (payloads.first() == THUMB) {
holder.binding.btnThumbUp.setThumbUpIcon(item.post.likeCommentStatus)
holder.binding.btnThumbDown.setThumbDownIcon(item.post.unlikeCommentStatus)
holder.binding.btnThumbUp.text = item.realLikesCount?.toString()
}
}

Expand Down Expand Up @@ -203,6 +221,22 @@ class VideoCommentRvAdapter(private val fragment: Fragment? = null) :
}
}

private fun MaterialButton.setThumbUpIcon(likeCommentStatus: Boolean) {
if (likeCommentStatus) {
setIconResource(R.drawable.ic_baseline_thumb_up_alt_24)
} else {
setIconResource(R.drawable.ic_baseline_thumb_up_off_alt_24)
}
}

private fun MaterialButton.setThumbDownIcon(unlikeCommentStatus: Boolean) {
if (unlikeCommentStatus) {
setIconResource(R.drawable.ic_baseline_thumb_down_alt_24)
} else {
setIconResource(R.drawable.ic_baseline_thumb_down_off_alt_24)
}
}

// stackoverflow-36801486
private fun TextView.fixTextSelection() {
setTextIsSelectable(false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class DownloadingFragment : YenalyFragment<FragmentListOnlyBinding, DownloadView
binding.rvList.layoutManager = LinearLayoutManager(context)
binding.rvList.adapter = adapter
adapter.setStateViewLayout(R.layout.layout_empty_view)
binding.rvList.itemAnimator?.changeDuration = 0
// binding.rvList.itemAnimator?.changeDuration = 0
}

override fun bindDataObservers() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,6 @@ class CommentFragment : YenalyFragment<FragmentCommentBinding, CommentViewModel>
is WebsiteState.Loading -> Unit
is WebsiteState.Success -> {
viewModel.handleCommentLike(state.info)
commentAdapter.notifyItemChanged(state.info.commentPosition, 0)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,13 +154,15 @@ class CommentViewModel(application: Application) : YenalyViewModel(application)
when (commentPlace) {
CommentPlace.COMMENT -> _videoCommentFlow.update { prevList ->
prevList.toMutableList().apply {
this[commentPosition].handleCommentLike(argState.info)
this[commentPosition] =
this[commentPosition].handleCommentLike(argState.info)
}
}

CommentPlace.CHILD_COMMENT -> _videoReplyFlow.update { prevList ->
prevList.toMutableList().apply {
this[commentPosition].handleCommentLike(argState.info)
this[commentPosition] =
this[commentPosition].handleCommentLike(argState.info)
}
}
}
Expand All @@ -169,12 +171,12 @@ class CommentViewModel(application: Application) : YenalyViewModel(application)
}
}

private fun VideoComments.VideoComment.handleCommentLike(args: VideoCommentArguments) {
if (args.isPositive) {
this.incrementLikesCount(cancel = post.likeCommentStatus)
} else {
this.decrementLikesCount(cancel = post.unlikeCommentStatus)
}
private fun VideoComments.VideoComment.handleCommentLike(
args: VideoCommentArguments,
) = if (args.isPositive) {
this.incrementLikesCount(cancel = post.likeCommentStatus)
} else {
this.decrementLikesCount(cancel = post.unlikeCommentStatus)
}

fun handleCommentLike(args: VideoCommentArguments) {
Expand Down

0 comments on commit fb4dcd4

Please sign in to comment.