使用MVP模式从recyclerview适配器更新视图

时间:2018-04-18 10:53:19

标签: android design-patterns android-recyclerview mvp

我有一个名为" OverviewFragment"我有一位主持人和合同。我正在使用"概述片段"创建一个recyclerview适配器。

我对如何在recyclerview中填充内容有一些疑问。我已经读过适配器应该只作为MVP中的View。 但是我有一些条件要满足在recyclerview中显示内容。我应该在哪里写这个业务逻辑?

在SO中也有答案我们不应该为视图持有者创建演示者。所以基本上我需要在适配器中编写业务逻辑来填充recyclerview中的内容,或者我需要将其链接到"概述"片段,然后在片段演示者中执行业务逻辑。

哪种方法正确?

1 个答案:

答案 0 :(得分:0)

这就是我解决这个问题的方法。首先是位于域级别的所有业务逻辑,但您可以创建任何其他抽象级别以将数据模型映射到视图层模型。 因此,只有位于演示级别的特定模型。然后我们的适配器看起来像这样:

class CustomerCardsAdapter(
    var cards: MutableList<ListItem> = mutableListOf()
) : RecyclerView.Adapter<CustomerCardsAdapter.ItemViewHolder>() {

    lateinit var cardItemClick: (cardId: ClientCard) -> Unit

    override fun getItemViewType(position: Int) = cards[position].getListItemType().ordinal

    override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): CustomerCardsAdapter.ItemViewHolder {
        val resId = when (ItemType.values()[viewType]) {
            ItemType.CARD -> R.layout.card_item
            ItemType.SIMPLE_ITEM -> R.layout.account_simple_item_view
            else -> throw IllegalArgumentException("viewType = $viewType create not support")
        }
        val view = LayoutInflater.from(viewGroup.context).inflate(resId, viewGroup, false)
        return ItemViewHolder(view)
    }

    override fun onBindViewHolder(viewHolder: ItemViewHolder, position: Int) {
        val item = cards[position]
        when (item.getListItemType()) {
            ItemType.CARD -> viewHolder.populateCard(item)
            ItemType.SIMPLE_ITEM -> viewHolder.populateSimpleItem(item)
            else -> throw IllegalArgumentException("viewType = ${item.getListItemType()} create not support")
        }
    }

    override fun getItemCount() = cards.size

    inner class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

        fun populateCard(item: ListItem) {
            with(itemView as CustomerCardView) {
                val card = item as ClientCard
                populate(card)
                setOnClickListener { cardItemClick(card) }
            }
        }

        fun populateSimpleItem(item: ListItem) {
            with(itemView as SimpleItemView) {
                val simpleItem = item as SimpleItem
                populate(simpleItem)
                setOnClickListener { simpleItem.action() }
            }
        }
    }
}

所以onCreateViewHolder只是膨胀视图和onBindViewHolder方法调用ViewHolders方法来填充数据。

从View类继承的RecyclerView项,包含实际向Views提供数据的逻辑。

private const val CORNER_RADIUS = 4f
private const val SHADOW_ALPHA = 60

class CustomerCardView
@JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0)
    : LinearLayout(context, attrs, defStyleAttr) {

    private val imageCard by bind<BlurryCardView>(R.id.card_image)
    private val cardNumberTextView by bind<TextView>(R.id.card_number_text_view)
    private val imageIps by bind<IpsImageView>(R.id.card_image_ips)
    private val cardNameTextView by bind<TextView>(R.id.card_name_text_view)
    private val cardActivateView by bind<View>(R.id.card_activate)
    private val cardBlockView by bind<View>(R.id.card_unblock)
    private val imageContactlessPayView by bind<ImageView>(R.id.image_contactless_pay)
    private val smsNotificationsView by bind<ImageView>(R.id.image_sms_notifications)
    private val shadowView by bind<ShadowContainer>(R.id.card_shadow)

    fun populate(card: ClientCard) {
        with(card) {
            cardNameTextView.text = name
            cardNumberTextView.text = when {
                isNotActiveOnlyTokenization -> context.getString(R.string.card_is_not_active_only_tokenization)
                isTokenizationNotActivation -> context.getString(R.string.card_is_tokenization_not_activation)
                isTokenizationAndActivation -> context.getString(R.string.card_is_tokenization_and_activation)
                isBlockedToken -> context.getString(R.string.card_is_blocked_token)
                !isActivated -> context.getString(R.string.card_not_activated_text)
                supportsUnblocking() -> context.getString(R.string.card_blocked_text)
                isActivated && !supportsUnblocking() -> {
                    maskLast4Symbols(number)
                }
                else -> maskLast4Symbols(number)
            }
            imageContactlessPayView.setVisibility(tokens.isNotEmpty())
            smsNotificationsView.setVisibility(isAlfaCheck)

            populateCardImage(card)
        }
    }

    private fun populateCardImage(card: ClientCard) {
        imageCard.setCornerRadius(CORNER_RADIUS)
        shadowView.shadowParams.shadowAlpha = SHADOW_ALPHA
        post {
            val url = ImageUrlFactory.createUrl(card.cardType, imageCard.width, imageCard.height)
            imageCard.populateImage(url, {
                imageIps.populateWhite(card.ips)
                changeVisibility(card)
            })
        }
    }

    private fun changeVisibility(card: ClientCard) {
        with(card) {
            val blocked = (isLocked && isActivated && !isNotActiveOnlyTokenization) || isBlockedToken
            cardActivateView.setVisibility(card.showIsNotActiveIcon())
            cardBlockView.setVisibility(blocked)
        }
    }
}