Epoxy : start using viewholder instead of kotlin model as it's more efficient

This commit is contained in:
ganfra 2019-02-19 10:31:05 +01:00
parent 264265a1f7
commit c467f179e1
5 changed files with 105 additions and 85 deletions

View File

@ -32,14 +32,13 @@ class GroupSummaryController(private val callback: Callback? = null
} }
summaries.forEach { groupSummary -> summaries.forEach { groupSummary ->
val isSelected = groupSummary.groupId == selected?.groupId val isSelected = groupSummary.groupId == selected?.groupId
GroupSummaryItem( groupSummaryItem {
groupName = groupSummary.displayName, id(groupSummary.groupId)
avatarUrl = groupSummary.avatarUrl, groupName(groupSummary.displayName)
isSelected = isSelected, selected(isSelected)
listener = { callback?.onGroupSelected(groupSummary) } avatarUrl(groupSummary.avatarUrl)
) listener { callback?.onGroupSelected(groupSummary) }
.id(groupSummary.groupId) }
.addTo(this)
} }
} }



View File

@ -17,25 +17,32 @@
package im.vector.riotredesign.features.home.group package im.vector.riotredesign.features.home.group


import android.widget.ImageView import android.widget.ImageView
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import com.airbnb.epoxy.EpoxyModelWithHolder
import im.vector.riotredesign.R import im.vector.riotredesign.R
import im.vector.riotredesign.core.epoxy.KotlinModel import im.vector.riotredesign.core.epoxy.KotlinEpoxyHolder
import im.vector.riotredesign.core.platform.CheckableFrameLayout import im.vector.riotredesign.core.platform.CheckableFrameLayout
import im.vector.riotredesign.features.home.AvatarRenderer import im.vector.riotredesign.features.home.AvatarRenderer


@EpoxyModelClass(layout = R.layout.item_group)
abstract class GroupSummaryItem : EpoxyModelWithHolder<GroupSummaryItem.Holder>() {


data class GroupSummaryItem( @EpoxyAttribute lateinit var groupName: CharSequence
val groupName: CharSequence, @EpoxyAttribute var avatarUrl: String? = null
val avatarUrl: String?, @EpoxyAttribute var selected: Boolean = false
val isSelected: Boolean, @EpoxyAttribute var listener: (() -> Unit)? = null
val listener: (() -> Unit)? = null
) : KotlinModel(R.layout.item_group) {


private val avatarImageView by bind<ImageView>(R.id.groupAvatarImageView) override fun bind(holder: Holder) {
private val rootView by bind<CheckableFrameLayout>(R.id.itemGroupLayout) super.bind(holder)

holder.rootView.isSelected = selected
override fun bind() { holder.rootView.setOnClickListener { listener?.invoke() }
rootView.isSelected = isSelected AvatarRenderer.render(avatarUrl, groupName.toString(), holder.avatarImageView)
rootView.setOnClickListener { listener?.invoke() }
AvatarRenderer.render(avatarUrl, groupName.toString(), avatarImageView)
} }

class Holder : KotlinEpoxyHolder() {
val avatarImageView by bind<ImageView>(R.id.groupAvatarImageView)
val rootView by bind<CheckableFrameLayout>(R.id.itemGroupLayout)
}

} }

View File

@ -20,33 +20,39 @@ import android.view.ViewGroup
import android.widget.TextView import android.widget.TextView
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.graphics.drawable.DrawableCompat import androidx.core.graphics.drawable.DrawableCompat
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import com.airbnb.epoxy.EpoxyModelWithHolder
import im.vector.riotredesign.R import im.vector.riotredesign.R
import im.vector.riotredesign.core.epoxy.KotlinModel import im.vector.riotredesign.core.epoxy.KotlinEpoxyHolder


data class RoomCategoryItem( @EpoxyModelClass(layout = R.layout.item_room_category)
val title: CharSequence, abstract class RoomCategoryItem : EpoxyModelWithHolder<RoomCategoryItem.Holder>() {
val isExpanded: Boolean,
val unreadCount: Int,
val showHighlighted: Boolean,
val listener: (() -> Unit)? = null
) : KotlinModel(R.layout.item_room_category) {


private val unreadCounterBadgeView by bind<UnreadCounterBadgeView>(R.id.roomCategoryUnreadCounterBadgeView) @EpoxyAttribute lateinit var title: CharSequence
private val titleView by bind<TextView>(R.id.roomCategoryTitleView) @EpoxyAttribute var expanded: Boolean = false
private val rootView by bind<ViewGroup>(R.id.roomCategoryRootView) @EpoxyAttribute var unreadCount: Int = 0
@EpoxyAttribute var showHighlighted: Boolean = false
@EpoxyAttribute var listener: (() -> Unit)? = null


private val tintColor by lazy { override fun bind(holder: Holder) {
ContextCompat.getColor(rootView.context, R.color.bluey_grey_two) val tintColor = ContextCompat.getColor(holder.rootView.context, R.color.bluey_grey_two)
} val expandedArrowDrawableRes = if (expanded) R.drawable.ic_expand_more_white else R.drawable.ic_expand_less_white

val expandedArrowDrawable = ContextCompat.getDrawable(holder.rootView.context, expandedArrowDrawableRes)?.also {
override fun bind() {
val expandedArrowDrawableRes = if (isExpanded) R.drawable.ic_expand_more_white else R.drawable.ic_expand_less_white
val expandedArrowDrawable = ContextCompat.getDrawable(rootView.context, expandedArrowDrawableRes)?.also {
DrawableCompat.setTint(it, tintColor) DrawableCompat.setTint(it, tintColor)
} }
unreadCounterBadgeView.render(unreadCount, showHighlighted) holder.unreadCounterBadgeView.render(unreadCount, showHighlighted)
titleView.setCompoundDrawablesWithIntrinsicBounds(expandedArrowDrawable, null, null, null) holder.titleView.setCompoundDrawablesWithIntrinsicBounds(expandedArrowDrawable, null, null, null)
titleView.text = title holder.titleView.text = title
rootView.setOnClickListener { listener?.invoke() } holder.rootView.setOnClickListener { listener?.invoke() }
} }


class Holder : KotlinEpoxyHolder() {
val unreadCounterBadgeView by bind<UnreadCounterBadgeView>(R.id.roomCategoryUnreadCounterBadgeView)
val titleView by bind<TextView>(R.id.roomCategoryTitleView)
val rootView by bind<ViewGroup>(R.id.roomCategoryRootView)
}

} }


View File

@ -85,18 +85,17 @@ class RoomSummaryController(private val stringProvider: StringProvider
summaries.map { it.notificationCount }.reduce { acc, i -> acc + i } summaries.map { it.notificationCount }.reduce { acc, i -> acc + i }
} }
val showHighlighted = summaries.any { it.highlightCount > 0 } val showHighlighted = summaries.any { it.highlightCount > 0 }
RoomCategoryItem( roomCategoryItem {
title = stringProvider.getString(titleRes).toUpperCase(), id(titleRes)
isExpanded = isExpanded, title(stringProvider.getString(titleRes).toUpperCase())
unreadCount = unreadCount, expanded(isExpanded)
showHighlighted = showHighlighted, unreadCount(unreadCount)
listener = { showHighlighted(showHighlighted)
listener {
mutateExpandedState() mutateExpandedState()
setData(viewState) setData(viewState)
} }
) }
.id(titleRes)
.addTo(this)
} }


private fun buildRoomModels(summaries: List<RoomSummary>, selectedRoomId: String?) { private fun buildRoomModels(summaries: List<RoomSummary>, selectedRoomId: String?) {
@ -104,16 +103,16 @@ class RoomSummaryController(private val stringProvider: StringProvider
val unreadCount = roomSummary.notificationCount val unreadCount = roomSummary.notificationCount
val showHighlighted = roomSummary.highlightCount > 0 val showHighlighted = roomSummary.highlightCount > 0
val isSelected = roomSummary.roomId == selectedRoomId val isSelected = roomSummary.roomId == selectedRoomId
RoomSummaryItem(
roomName = roomSummary.displayName, roomSummaryItem {
avatarUrl = roomSummary.avatarUrl, id(roomSummary.roomId)
isSelected = isSelected, roomName(roomSummary.displayName)
showHighlighted = showHighlighted, avatarUrl(roomSummary.avatarUrl)
unreadCount = unreadCount, selected(isSelected)
listener = { callback?.onRoomSelected(roomSummary) } showHighlighted(showHighlighted)
) unreadCount(unreadCount)
.id(roomSummary.roomId) listener { callback?.onRoomSelected(roomSummary) }
.addTo(this) }
} }
} }



View File

@ -18,31 +18,40 @@ package im.vector.riotredesign.features.home.room.list


import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import com.airbnb.epoxy.EpoxyModelWithHolder
import im.vector.riotredesign.R import im.vector.riotredesign.R
import im.vector.riotredesign.core.epoxy.KotlinModel import im.vector.riotredesign.core.epoxy.KotlinEpoxyHolder
import im.vector.riotredesign.core.platform.CheckableFrameLayout import im.vector.riotredesign.core.platform.CheckableFrameLayout
import im.vector.riotredesign.features.home.AvatarRenderer import im.vector.riotredesign.features.home.AvatarRenderer




data class RoomSummaryItem( @EpoxyModelClass(layout = R.layout.item_room)
val roomName: CharSequence, abstract class RoomSummaryItem : EpoxyModelWithHolder<RoomSummaryItem.Holder>() {
val avatarUrl: String?,
val isSelected: Boolean,
val unreadCount: Int,
val showHighlighted: Boolean,
val listener: (() -> Unit)? = null
) : KotlinModel(R.layout.item_room) {


private val unreadCounterBadgeView by bind<UnreadCounterBadgeView>(R.id.roomUnreadCounterBadgeView) @EpoxyAttribute lateinit var roomName: CharSequence
private val titleView by bind<TextView>(R.id.roomNameView) @EpoxyAttribute var avatarUrl: String? = null
private val avatarImageView by bind<ImageView>(R.id.roomAvatarImageView) @EpoxyAttribute var selected: Boolean = false
private val rootView by bind<CheckableFrameLayout>(R.id.itemRoomLayout) @EpoxyAttribute var unreadCount: Int = 0
@EpoxyAttribute var showHighlighted: Boolean = false
@EpoxyAttribute var listener: (() -> Unit)? = null


override fun bind() {
unreadCounterBadgeView.render(unreadCount, showHighlighted) override fun bind(holder: Holder) {
rootView.isChecked = isSelected super.bind(holder)
rootView.setOnClickListener { listener?.invoke() } holder.unreadCounterBadgeView.render(unreadCount, showHighlighted)
titleView.text = roomName holder.rootView.isChecked = selected
AvatarRenderer.render(avatarUrl, roomName.toString(), avatarImageView) holder.rootView.setOnClickListener { listener?.invoke() }
holder.titleView.text = roomName
AvatarRenderer.render(avatarUrl, roomName.toString(), holder.avatarImageView)
} }

class Holder : KotlinEpoxyHolder() {
val unreadCounterBadgeView by bind<UnreadCounterBadgeView>(R.id.roomUnreadCounterBadgeView)
val titleView by bind<TextView>(R.id.roomNameView)
val avatarImageView by bind<ImageView>(R.id.roomAvatarImageView)
val rootView by bind<CheckableFrameLayout>(R.id.itemRoomLayout)
}

} }