MergeAdapterを使用してアダプタコードをよりクリーンにする

下の写真のように、プロジェクト内の過負荷で複雑なアダプターにうんざりしていませんか?新しいセルタイプを追加するたびに、RecyclerViewのアダプターを書き直して、コードを読みやすくしますか?多くのアプローチがありますが、ほとんどの場合、デリゲートアダプタアプローチを使用することをお勧めします。たとえば、この記事で理解できる、グループ化などのさまざまなタイプのビューでリストを動的に作成するためのライブラリを使用することをお勧めします。しかし、今日は、さまざまなセルのアダプターのロジックをカプセル化して、SOLIDの原則に準拠するのに役立つ新しいクラスについて説明します。



画像



MergeAdapterは、recyclerview:1.2.0-alpha02導入された新しいクラスであり、複数のディスプレイアダプターを単一のRecyclerViewに組み合わせることができます。これにより、アダプタ内の各セルのロジックをカプセル化できるようになり、将来的に再利用できるようになります。



問題



例から始めましょう。説明付きのテキストと画像の2種類のデータを含むフィードを表示するタスクがあるとします。onCreateViewHolder 最も一般的な場合のメソッドのコードは次のようになります。



override fun onCreateViewHolder(
    parent: ViewGroup, viewType: Int
): RecyclerView.ViewHolder? {
    val holder: RecyclerView.ViewHolder
    val inflater = LayoutInflater.from(parent.context)
    when (viewType) {
        TEXT_VIEW_TYPE -> {
            holder = TextViewHolder(
                inflater.inflate(R.layout.text_item, parent, false)
            )
        }
        IMAGE_VIEW_TYPE -> {
            holder = ImageViewHolder(
                inflater.inflate(R.layout.image_item, parent, false),
                imageClickListener
            )
        }
        else -> {
            throw IllegalArgumentException(
                "Can't create view holder from view type $viewType"
            )
        }
    }
    return holder
}


なぜそれが悪いのですか?この実装の欠点は、DRYとSOLIDの原則に違反していることです(単一の責任とオープンクローズ)。これを確認するには、2つの要件を追加するだけで十分です。新しいデータタイプ(チェックボックス)を入力し、もう1つのテープを入力します。ここには、チェックボックスと画像のみが表示されます。



2番目のテープに同じアダプターを使用するか、新しいテープを作成するか、という選択肢に直面しています。選択したソリューションに関係なく、コードを変更する必要があります(ほぼ同じですが、場所が異なります)。新しいVIEW_TYPE、ViewHolder new、およびeditメソッドを追加する必要がありますgetItemViewType(), onCreateViewHolder() onBindViewHolder()



1つのアダプターを保持することにした場合、変更はそこで終了します。ただし、将来、新しいロジックを持つ新しいデータタイプが2番目のフィードにのみ追加される場合、最初のフィードには追加の機能があり、変更されていませんが、テストする必要があります。



新しいアダプタを作成することにした場合、重複するコードがたくさんあります。



決定



新しいMergeAdapterクラスを使用すると、さまざまな種類のセルにさまざまなアダプターを組み合わせることができます。たとえば、非常に一般的な使用例は、フィードにデータをロードしているときにスピナーを表示し、突然ロードエラーが発生した場合、フィードの最後にエラーのあるセルを表示することです。



画像



この問題の解決策は、MergeAdapterを使用することです。3つのアダプターがあるとします。




val firstAdapter: FirstAdapter = …
val secondAdapter: SecondAdapter = …
val thirdAdapter: ThirdAdapter = …val mergeAdapter = MergeAdapter(firstAdapter, secondAdapter, thirdAdapter)
recyclerView.adapter = mergeAdapter


RecyclerViewは、コンストラクターに渡されたのと同じ順序で、各アダプターのアイテムを順番に表示します。アダプターが異なれば、リスト内のセルごとにロジックを分離できます。たとえば、リストにタイトルを追加する必要がある場合、リストのメインコンテンツの表示を担当するアダプタにこのロジックを実装する必要はありません。さまざまなタイプのセルに対してアダプタを分離できます。このアプローチは、ロジックをカプセル化し、将来的にさまざまな画面で再利用するのに役立ちます。



画像



ダウンロードをヘッダーまたはリストの下部に表示します。



リストの上部または下部にダウンロードステータスを表示するには、それぞれアダプタを追加する必要があります。



val mergeAdapter = MergeAdapter(headerAdapter, listAdapter, footerAdapter)
recyclerView.adapter = mergeAdapter


上のセルと下のセルは、同じレイアウト、ViewHolder、およびUIロジックを使用します(ロードステータスの表示と非表示)。一般に、リストの上部と下部に同じアダプターの2つのインスタンスを使用するだけで十分です。例はここまたはここにあります



つまり、さまざまなタイプのセルで複雑なアダプターを使用する場合、このような簡単な方法でプロジェクトのコードを改善できます。



あなたはその記事が好きでしたか?Telegramに参加すること忘れないでください。また、Android開発者向けの便利な資料や最新のチュートリアルがAndroidSchool.ruプラットフォームで公開されています



All Articles