我们可以使用Kotlin的高阶函数来创建RecyclerView CustomViewHolder吗?

时间:2018-08-21 17:01:16

标签: android android-recyclerview kotlin higher-order-functions

我想创建一个辅助方法,以使其非常容易在Android中设置新的RecyclerView。我是通过以下辅助类实现的:

class AirRv {

    companion object {

        fun initAndGetAdapter(
                rv : RecyclerView,
                layoutManager: RecyclerView.LayoutManager,
                viewLayout: Int,
                viewHolder: (view: View) -> RecyclerView.ViewHolder,
                bindView: (viewHolder: RecyclerView.ViewHolder, position: Int) -> Unit,
                size: () -> Int
        ): RecyclerView.Adapter<RecyclerView.ViewHolder>
        {
            return initAndGetAdapter(
                    rv,
                    layoutManager,
                    {
                        0
                    },
                    {
                        viewLayout
                    },
                    fun(view: View, viewType: Int) : RecyclerView.ViewHolder {
                        return viewHolder(view)
                    },
                    fun(viewHolder: RecyclerView.ViewHolder, viewType: Int, position: Int) {
                        bindView(viewHolder, position)
                    },
                    { size.invoke() }
            )
        }

        fun initAndGetAdapter(
                rv: RecyclerView,
                layoutManager: RecyclerView.LayoutManager,
                viewType: (position: Int) -> Int,
                viewLayout: (viewType: Int) -> Int,
                viewHolder: (view: View, viewType: Int) -> RecyclerView.ViewHolder,
                bindView: (viewHolder: RecyclerView.ViewHolder, viewType: Int, position: Int) -> Unit,
                size: () -> Int

        ): RecyclerView.Adapter<RecyclerView.ViewHolder>
        {
            val rvAdapter = object : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

                override fun getItemViewType(position: Int): Int {
                    return viewType(position)
                }

                override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
                    val view = LayoutInflater.from(rv.context).inflate(viewLayout(viewType), parent, false)
                    return viewHolder(view, viewType)
                }

                override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
                    bindView(holder, viewType(position), position)
                }

                override fun getItemCount(): Int {
                    return size()
                }

            }

            rv.layoutManager = layoutManager
            rv.adapter = rvAdapter
            return rvAdapter
        }

    }

}

这是我的实现示例:

val adapter = AirRv.initAndGetAdapter(
                rv,
                LinearLayoutManager(this),
                R.layout.item_layout,
                fun(view: View) : RecyclerView.ViewHolder {
                    return RvViewHolder(view)     // NOTICE THIS LINE
                },
                fun(viewHolder: RecyclerView.ViewHolder, position: Int) {
                    val value = arrayList.get(position).toString()
                    val rvViewHolder = viewHolder as RvViewHolder
                    rvViewHolder.textView.text = value
                },
                { arrayList.size }
        )

这很好。但我可以改善这一点吗?

RvViewHolder(view)(第6行)

所有封闭函数所做的只是传递视图并检索相应的viewHolder。使用Kotlin的高阶函数,就不可能以某种方式接收函数定义,以便助手方法可以创建实例并做必要的操作以在内部获取相应的viewHolder。

此辅助函数的最终用户(程序员)不应手动执行此操作。可以预见的是,当帮助程序库将给他一个视图时,用户将返回一个viewHolder。该程序为什么不能在内部执行该操作?

如果有人可以阐明此事,将不胜感激。

1 个答案:

答案 0 :(得分:0)

如果只有一种方法可以对泛型类型进行操作...

哦,等等。有,这就是所谓的泛型!

配套功能的签名应如下所示:

fun <T> initAndGetAdapter(
                rv : RecyclerView,
                layoutManager: RecyclerView.LayoutManager,
                viewLayout: Int,
                viewHolder: (view: View) -> T,
                bindView: (viewHolder: T, position: Int) -> Unit,
                size: () -> Int
): RecyclerView.Adapter<T>

还有

fun <T> initAndGetAdapter(
            rv: RecyclerView,
            layoutManager: RecyclerView.LayoutManager,
            viewType: (position: Int) -> Int,
            viewLayout: (viewType: Int) -> Int,
            viewHolder: (view: View, viewType: Int) -> T,
            bindView: (viewHolder: T, viewType: Int, position: Int) -> Unit,
            size: () -> Int

): RecyclerView.Adapter<T>

分别。

那么您就不必一直都上载到RecyclerView.ViewHolder
另外,无需进行不安全的as强制转换:

val adapter = AirRv.initAndGetAdapter(
        rv,
        LinearLayoutManager(""),
        1,
        fun(view: View) : RvViewHolder {
            return RvViewHolder(view)     // NOTICE THIS LINE
        },
        fun(viewHolder: RvViewHolder, position: Int) {
            val rvViewHolder = viewHolder // No as RvViewHolder anymore
        },
        { arrayList.size }
)

那些2005年的家伙肯定知道他们在做什么。

请记住,我没有完整的代码,因此您必须随时进行一些调整。

您可以在Kotlin here中阅读有关泛型的更多信息。