From 0d423c1ce4b0412cb8f6b6c187bf405afd0594ae Mon Sep 17 00:00:00 2001 From: Niko Diamadis Date: Sat, 18 Nov 2023 15:13:44 +0100 Subject: [PATCH] Switch to ListAdapter (replacing RecyclerView.Adapter) (#321) --- .../gotify/messages/ListMessageAdapter.kt | 31 +++++++++--- .../gotify/messages/MessagesActivity.kt | 49 +++++++------------ 2 files changed, 41 insertions(+), 39 deletions(-) diff --git a/app/src/main/kotlin/com/github/gotify/messages/ListMessageAdapter.kt b/app/src/main/kotlin/com/github/gotify/messages/ListMessageAdapter.kt index 04d092f5..a11f0500 100644 --- a/app/src/main/kotlin/com/github/gotify/messages/ListMessageAdapter.kt +++ b/app/src/main/kotlin/com/github/gotify/messages/ListMessageAdapter.kt @@ -14,6 +14,8 @@ import android.widget.ImageView import android.widget.TextView import android.widget.Toast import androidx.preference.PreferenceManager +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView import androidx.viewbinding.ViewBinding import com.github.gotify.MarkwonFactory @@ -34,9 +36,8 @@ internal class ListMessageAdapter( private val context: Context, private val settings: Settings, private val picasso: Picasso, - var items: List, private val delete: Delete -) : RecyclerView.Adapter() { +) : ListAdapter(DiffCallback) { private val prefs: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) private val markwon: Markwon = MarkwonFactory.createForMessage(context, picasso) @@ -70,7 +71,7 @@ internal class ListMessageAdapter( } override fun onBindViewHolder(holder: ViewHolder, position: Int) { - val message = items[position] + val message = currentList[position] if (Extras.useMarkdown(message.message)) { holder.message.autoLinkMask = 0 markwon.setMarkdown(holder.message, message.message.message) @@ -92,14 +93,12 @@ internal class ListMessageAdapter( holder.date.setOnClickListener { holder.switchTimeFormat() } holder.delete.setOnClickListener { - delete.delete(holder.adapterPosition, message.message, false) + delete.delete(message.message) } } - override fun getItemCount() = items.size - override fun getItemId(position: Int): Long { - val currentItem = items[position] + val currentItem = currentList[position] return currentItem.message.id } @@ -184,7 +183,23 @@ internal class ListMessageAdapter( } } + object DiffCallback : DiffUtil.ItemCallback() { + override fun areItemsTheSame( + oldItem: MessageWithImage, + newItem: MessageWithImage + ): Boolean { + return oldItem.message.id == newItem.message.id + } + + override fun areContentsTheSame( + oldItem: MessageWithImage, + newItem: MessageWithImage + ): Boolean { + return oldItem == newItem + } + } + fun interface Delete { - fun delete(position: Int, message: Message, listAnimation: Boolean) + fun delete(message: Message) } } diff --git a/app/src/main/kotlin/com/github/gotify/messages/MessagesActivity.kt b/app/src/main/kotlin/com/github/gotify/messages/MessagesActivity.kt index 929fa708..7ea59335 100644 --- a/app/src/main/kotlin/com/github/gotify/messages/MessagesActivity.kt +++ b/app/src/main/kotlin/com/github/gotify/messages/MessagesActivity.kt @@ -101,14 +101,9 @@ internal class MessagesActivity : listMessageAdapter = ListMessageAdapter( this, viewModel.settings, - viewModel.picassoHandler.get(), - emptyList() - ) { position, message, listAnimation -> - scheduleDeletion( - position, - message, - listAnimation - ) + viewModel.picassoHandler.get() + ) { message -> + scheduleDeletion(message) } addBackPressCallback() @@ -329,7 +324,6 @@ internal class MessagesActivity : } } } - listMessageAdapter.notifyDataSetChanged() selectAppInMenu(binding.navView.menu.findItem(selectedIndex)) super.onResume() } @@ -348,20 +342,11 @@ internal class MessagesActivity : } } - private fun scheduleDeletion( - position: Int, - message: Message, - listAnimation: Boolean - ) { + private fun scheduleDeletion(message: Message) { val adapter = binding.messagesView.adapter as ListMessageAdapter val messages = viewModel.messages messages.deleteLocal(message) - adapter.items = messages[viewModel.appId] - if (listAnimation) { - adapter.notifyItemRemoved(position) - } else { - adapter.notifyDataSetChanged() - } + adapter.updateList(messages[viewModel.appId]) showDeletionSnackbar() } @@ -371,13 +356,7 @@ internal class MessagesActivity : if (deletion != null) { val adapter = binding.messagesView.adapter as ListMessageAdapter val appId = viewModel.appId - adapter.items = messages[appId] - val insertPosition = if (appId == MessageState.ALL_MESSAGES) { - deletion.allPosition - } else { - deletion.appPosition - } - adapter.notifyItemInserted(insertPosition) + adapter.updateList(messages[appId]) } } @@ -432,8 +411,8 @@ internal class MessagesActivity : override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { val position = viewHolder.adapterPosition - val message = adapter.items[position] - scheduleDeletion(position, message.message, true) + val message = adapter.currentList[position] + scheduleDeletion(message.message) } override fun onChildDraw( @@ -649,8 +628,16 @@ internal class MessagesActivity : binding.flipper.displayedChild = 0 } val adapter = binding.messagesView.adapter as ListMessageAdapter - adapter.items = messageWithImages - adapter.notifyDataSetChanged() + adapter.updateList(messageWithImages) + } + + private fun ListMessageAdapter.updateList(list: List) { + this.submitList(if (this.currentList == list) list.toList() else list) { + val topChild = binding.messagesView.getChildAt(0) + if (topChild != null && topChild.top == 0) { + binding.messagesView.scrollToPosition(0) + } + } } companion object {