Skip to content

Instantly share code, notes, and snippets.

@Sharkaboi
Last active January 27, 2022 11:55
Show Gist options
  • Save Sharkaboi/c4418f1ae2de9e5676658511d47415fa to your computer and use it in GitHub Desktop.
Save Sharkaboi/c4418f1ae2de9e5676658511d47415fa to your computer and use it in GitHub Desktop.
RecyclerView Adapter template with DiffUtil.ItemCallback, ViewBinding and custom listeners. Best when used with livedata.

Adapter Template


#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME}#end

import androidx.recyclerview.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.AsyncListDiffer
import androidx.recyclerview.widget.DiffUtil

#parse("File Header.java")
class ${NAME}(private val customListeners: CustomListeners) : 
  RecyclerView.Adapter<${NAME}.${ViewHolder_Class}>(){

  private val diffUtilItemCallback = object: DiffUtil.ItemCallback<${Model_Class}>(){

    //pk is the primary key for the data class.
    //replace with any unique identifier of your specific data class.
    override fun areItemsTheSame(oldItem: ${Model_Class}, newItem: ${Model_Class}): Boolean {
      return oldItem.pk == newItem.pk
    }

    override fun areContentsTheSame(oldItem: ${Model_Class}, newItem: ${Model_Class}): Boolean {
      return oldItem == newItem
    }

  }
  
  private val listDiffer = AsyncListDiffer(this, diffUtilItemCallback)
  
  private lateinit var binding: ${ViewBinding_Class}

  override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ${ViewHolder_Class} {
      binding = ${ViewBinding_Class}.inflate(LayoutInflater.from(parent.context), parent, false)
      return ${ViewHolder_Class}(binding, customListeners)
  }

  override fun onBindViewHolder(holder: ${ViewHolder_Class}, position: Int) {
          holder.bind(listDiffer.currentList[position])
  }

  override fun getItemCount(): Int {
      return listDiffer.currentList.size
  }

  fun submitList(list: List<${Model_Class}>){
      listDiffer.submitList(list)
  }

  class ${ViewHolder_Class}
  constructor(
      private val binding: ${ViewBinding_Class},
      private val customListeners: CustomListeners
  ) : RecyclerView.ViewHolder(binding.root){
      
      fun bind(item: ${Model_Class}) {
      
          //Custom onClick for whole item onClick
          binding.root.setOnClickListener {
              //Pass respective parameter, adapterPosition or pk.
              customListeners.onItemSelected(item.pk)
          }
          
          //TODO : Bind your data to views here.
          //Use CustomListeners respective function for respective view's listeners.
      }
  }

  // Interface to be inherited by view to provide 
  //custom listeners for each item based on position 
  //or other custom parameters (ex : Primary key)
  
  interface CustomListeners {
      fun onItemSelected(position: Int)
      // add your view listeners here
      // ex : fun onSwitchChecked(..) , fun onItemLongPress(..)
  }  
}

Live templates how to

  1. Open settings.

settings

  1. Goto : Editor>File and Code Templates.

template

  1. Click Plus to Add new template and give appropriate name. Copy the above template and check the Reformat according to style option. Press ok to confirm.

create

Usage

  • Right click on the package you want to use the adapter and choose the option that you just made.

make

  • Provide necessary details as per your use

details

  • Import the ViewBinding class as well as your model class. Replace the todo's with your code :)

  • In the view, submit list as so and pass the implemented interface for the custom listeners. For example:

class MyFragment : Fragment(), MyAdapter.CustomListeners {
  override onViewCreated(..) {
    ..
    setupRecyclerView()
  }
  
  private fun setupRecyclerView() {
        // this is passed here as we're implementing the CustomListeners interface in the view where we have context
        val adapter = MyAdapter(this)

        myRecyclerView.apply {
            this.adapter = adapter
            //set layout manager, item animators etc here
        }

        myViewModel.myList.observe(viewLifecycleOwner, Observer {
            adapter.submitList(it)
        })
    }
   
    //implementing the interface's methods here
    override onItemSelected(position : Int){
      //implement your item click here
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment