0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

MVPでRecyclerViewをいい感じに使いたい

Posted at

概要

MVPアーキテクチャでRecyclerViewを使用したときに、
データ管理の方法に悩みました。
そのときの対応方法を書きます。

背景

RecyclerViewを使用するときに、
RecyclerView.Adapter内でデータを保持する実装が一般的だと思います。

ただ、RecyclerView.Adapterはクラス名からもわかるように、Viewに属するクラスです。
MVPで言えば、Vです。
VにMを持たせて操作させたくありません。
PがMを持ってVの更新をしたいです。

それをするために少し奮闘しました。

どうやって乗り切ったのか

RecyclerView.Adapterの実装

ほぼ空っぽに。

SampleListAdapter.kt
class SampleListAdapter(
        private val contentManager: ContentManager,
        private val contentViewCreator: ContentViewCreator,
        private val bindListener: OnBindListener
) : RecyclerView.Adapter<ViewHolder>() {

    interface ContentManager {
        fun getItemCount(): Int
        fun getItemViewType(position: Int): Int
    }

    interface ContentViewCreator {
        fun createContentView(context: Context): SampleContentView
        fun createCampaignContentView(context: Context): CampaignContentView
    }

    interface OnBindListener {
        fun onBindContentView(holder: SampleViewHolder, position: Int)
        fun onBindCampaignContentView(holder: CampaignViewHolder, position: Int)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
            when (findByViewType(viewType)) {
                default -> SampleViewHolder(contentViewCreator.createContentView(parent.context))
            }

    override fun getItemCount(): Int = contentManager.getItemCount()

    override fun getItemViewType(position: Int) = contentManager.getItemViewType(position)

    override fun onBindViewHolder(holder: ViewHolder, position: Int) =
            when (holder) {
                is SampleViewHolder -> bindListener.onBindContentView(holder, position)
                else -> throw IllegalArgumentException()
            }
}

Viewの実装

ちょっとボリューミーだけど、こんな感じ。

SampleFragment.kt
interface SampleView : BaseView {
    fun notifyData()
    fun setDataCount(count: Int)
    fun onBindContentViewHolder(holder: SampleViewHolder, model: SampleModel, position: Int)
}

class SampleFragment : Fragment, SampleView {

    fun setAdapter() {
        recyclerView.adapter = SampleListAdapter(
            object : SampleListAdapter.ContentManager {
                override fun getItemCount(): Int {
                    return presenter.getItemCount()
                }

                override fun getItemViewType(position: Int): Int {
                    return presenter.getViewType(position)
                }
            },
            object : SampleListAdapter.ContentViewCreator {
                override fun createContentView(context: Context): SampleContentView {
                    return SampleContentView(context)
                }
            },
            object : SampleListAdapter.OnBindListener {
                override fun onBindContentView(holder: SampleViewHolder, position: Int) {
                    presenter.onBindContentView(holder, position)
                }
            }
        )
    }
}

Presenterの実装

データが必要なところだけ、Presenterに返すようにする。

PresenterにViewHolderへの参照が入ってしまうのは致し方なし...
getter追加も苦肉の策...

SamplePresenter.kt
interface SamplePresenter : BasePresenter<SampleView> {
    fun getItemCount(): Int
    fun getViewType(position: Int): Int
    fun onBindContentView(viewHolder: SampleViewHolder, position: Int)
}

終わりに

若干の無茶はしつつも..
目的の PがMを持ってVの更新をしたい がRecylerViewでできました。

結構ざっくりとしかコードを載せていので、
これだけを見ると意味がわからない人も多くいる気がします。

もし要望が多ければ、サンプルプロジェクトを作って
GitHub にアップするかも..しないかも..しれないので、コメントいただければと。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?