Back last year I mentioned using a factory approach to getting Adapters rather than defining a class file for each Adapter. The advantage of this is that for less complex Adapters, you can save a lot of code, improve development efficiency and free hands, and better support for multi-type layouts.

Kotlin DSL and Adapter factory methods

You can use the Kotlin DSL as a builder. There’s a great article here, if you want to read it,

www.ximedes.com/2020-04-21/…

Kotlin’S DSL is an extension of an extension function, such as the commonly used with function,

public inline fun <T, R> with(receiver: T, block: T. () - >R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return receiver.block()
}
Copy the code

Here’s an extension of the generic T. T here is analogous to Builder in Java Builder mode, where a final object is created by calling build() after the method receives external parameters.

For the Adapter factory method, I used it in the following way,

fun <T> getAdapter(
    @LayoutRes itemLayout:Int,
    converter: (helper: BaseViewHolder.item: T) - >Unit.data: List<T>): Adapter<T> = Adapter(itemLayout, converter, data)

class Adapter<T>(
    @LayoutRes private val layout: Int.private val converter: (helper: BaseViewHolder, item: T) -> Unit.val list: List<T>
): BaseQuickAdapter<T, BaseViewHolder>(layout, list) {
    override fun convert(helper: BaseViewHolder, item: T) {
        converter(helper, item)
    }
}
Copy the code

That is, every time you want to get a Adapter, you just call the getAdapter() method. This encapsulation method is relatively simple and supports limited functions. As I slowly adopted the Kotlin DSL, I encapsulated the Kotlin DSL-style factory approach. Using Kotlin DSL style is more elegant and convenient, while better supporting multi-type layout effects.

2, use,

2.1 Importing Dependencies

First, the project relies on BRVAH, so you need to introduce the library after the dishes can be used. BRVAH is arguably the most useful Open source Adapter available today, so we didn’t have to reinvent the wheel ourselves. The best part of the framework design is that the ViewHolder controls are collected through SpareArray to avoid customizing viewholers, which is the basic idea behind our framework design.

The project has been uploaded to MavenCentral, you need to include the repository in your project first,

allprojects {
    repositories {
        mavenCentral()
    }
}
Copy the code

Then add the following dependencies to your project,

implementation "com.github.Shouheng88:xadapter:${latest_version}"
Copy the code

2.2 Using the Adapter factory method

After using xAdapter, when you need to define a Adapter, you don’t need to create a separate class file, you just need to get a Adapter through the createAdapter() method,

adapter = createAdapter {
    withType(Item::class.java, R.layout.item_eyepetizer_home) {
        // Bind data with viewholder.
        onBind { helper, item ->
            helper.setText(R.id.tv_title, item.data.title)
            helper.setText(R.id.tv_sub_title, item.data.author? .name +"|" + item.data.category)
            helper.loadCover(requireContext(), R.id.iv_cover, item.data.cover? .homepage, R.drawable.recommend_summary_card_bg_unlike) helper.loadRoundImage(requireContext(), R.id.iv_author, item.data.author? .icon, R.mipmap.eyepetizer,20f.dp2px())
        }
        // Item level click and long click events.onItemClick { _, _, position -> adapter? .getItem(position)? .let { toast("Clicked item: " + it.data.title)
            }
        }
    }
}
Copy the code

In this new call, you specify the data type and its corresponding layout file using the withType() method, and then bind the data to the ViewHolder in the onBind() method. The onBind() method is used here in the same way as the convert() method in BRVAH, and you can read the library to learn how to use it. In summary, xAapter makes a secondary encapsulation on top of BRVAH, which is, arguably, simpler than simple.

XAdapter supports binding click and hold events to each ViewHolder, as well as adding click and hold events to an individual View on the ViewHolder. As shown above, simply add the onItemClick() method and implement your own logic. You can refer to the project’s sample code for additional click events.

Effect,

2.3 Using Multiple Types of Adapter

Using a multi-type Adapter is very simple, similar to the above method, by adding a withType() method to createAdapter(). Here is an Adapter that can be quite complex to write, but with xAdpater’s invocation, it becomes quite simple,

private fun createAdapter(a) {
    adapter = createAdapter {
        withType(MultiTypeDataGridStyle::class.java, R.layout.item_list) {
            onBind { helper, item ->
                val rv = helper.getView<RecyclerView>(R.id.rv)
                rv.layoutManager = GridLayoutManager(context, 3)
                val adapter = createSubAdapter(R.layout.item_home_page_data_module_1, 1)
                rv.adapter = adapter
                adapter.setNewData(item.items)
            }
        }
        withType(MultiTypeDataListStyle1::class.java, R.layout.item_home_page_data_module_2) { onBind { helper, item -> converter.invoke(helper, item) } onItemClick { _, _, position -> (adapter? .getItem(position)as? MultiTypeDataListStyle1)? .let { toast("Clicked style[2] item: " + it.item.data.title)
                }
            }
        }
        withType(MultiTypeDataListStyle2::class.java, R.layout.item_list) {
            onBind { helper, item ->
                val rv = helper.getView<RecyclerView>(R.id.rv)
                rv.layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
                val adapter = createSubAdapter(R.layout.item_home_page_data_module_4, 3)
                rv.adapter = adapter
                adapter.setNewData(item.items)
            }
        }
        withType(MultiTypeDataListStyle3::class.java, R.layout.item_home_page_data_module_3) { onBind { helper, item -> converter.invoke(helper, item) } onItemClick { _, _, position -> (adapter? .getItem(position)as? MultiTypeDataListStyle3)? .let { toast("Clicked style[4] item: " + it.item.data.title)
                }
            }
        }
    }
}
Copy the code

XAdapter’s support for multitype layouts is a refinement of BRVAH, where data classes do not need to implement any classes and interfaces. Adpater internally distinguishes ViewHolder by Class.

Effect,

conclusion

Continuing to make complex calls when there is a more concise way to use them is like being left behind, and no amount of effort on the part of the programmer deserves any sympathy for doing repetitive, low-value work. The above is part of the function and code display, you can read the source code to learn more. I followed up by referring to other good library design ideas and supporting encapsulation of Adapter features for fast calls.