RecyclerView Adapter with ViewDataBinding

Viewed 63

I am creating a GenericAdapter for handling single row|item layouts. Everything working fine only view-binding is not updating data..

I want to get RecyclerView.ViewHolder binding in callback ,I know I can bind it in adapter using BR.item and executePending

I want viewDataBinding context in a Callback

holder.binding.name.text = mutableList[pos]

Above line in TestActivity not working properly

GenericAdapter.kt

class GenericAdapter<T,VB:ViewDataBinding>(
    var items:MutableList<T>,
    @LayoutRes val resLayoutID:Int,
    val onBind:(holder:GenericViewHolder<T,VB>,pos:Int) -> Unit
): RecyclerView.Adapter<GenericViewHolder<T,VB>>() {

    lateinit var mItemBinding:VB

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GenericViewHolder<T,VB> {
        val layoutInflater = LayoutInflater.from(parent.context)
        mItemBinding = DataBindingUtil.inflate(layoutInflater, resLayoutID, parent, false)
        return GenericViewHolder(mItemBinding)
    }
    override fun onBindViewHolder(holder: GenericViewHolder<T,VB>, position: Int) {
        onBind(holder,position)
    }
    override fun getItemCount(): Int = items.size
}

GenericViewHolder.kt

class GenericViewHolder<T,VB: ViewDataBinding>(val binding: VB)
    :RecyclerView.ViewHolder(binding.root){

    val mItemBinding:VB = binding
}

TestActivity.kt

class TestActivity:AppCompatActivity() {

    lateinit var recyclerView: RecyclerView
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_test)

        recyclerView = findViewById(R.id.recyclerView)
        recyclerView.layoutManager = LinearLayoutManager(this)
        recyclerView.setHasFixedSize(true)
        populateList()
    }

    private fun populateList(){
        val mutableList = mutableListOf<String>("apple","mango","tutti fruti","apricot",
            "apple","mango","tutti fruti","apricot",
            "apple","mango","tutti fruti","apricot",
            "apple","mango","tutti fruti","apricot")
        val mAdapter = GenericAdapter<String,ItemCountryBinding>(mutableList,R.layout.item_country){ holder,pos ->
        //val nameTv = holder.itemView.findViewById<TextView>(R.id.name)
        //nameTv.text = mutableList[pos]
        holder.binding.name.text = mutableList[pos]
    }
        recyclerView.adapter = mAdapter
    }
}

Where as below code working fine

val nameTv = holder.itemView.findViewById<TextView>(R.id.name)
nameTv.text = mutableList[pos]
1 Answers

I would recommend do onBind inside view holder. I don't see reason why you need this callback. You already passed mutableList to the adapter. For example here is my ViewHolder

class NewsViewHolder(private val binding: ListItemNewsBinding) : RecyclerView.ViewHolder(binding.root) {

    fun bind(news: RedditPost, itemClick: (RedditPost, View) -> Unit) {
        with(binding) {
            root.transitionName = news.thumbnail
            root.setOnClickListener { itemClick.invoke(news, binding.root) }

            title.text = news.title
            image.setImageUrl(news.thumbnail)
            author.text = news.author
            xHoursAgo.text = news.created_utc
            numComments.text = news.numComments
        }
    }
}

And

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
    if (isLoadingMore && position == (itemCount - 1)) return
    (holder as? NewsViewHolder)?.bind(news[position], itemClick)
}
Related