简体   繁体   中英

How to update live data of the viewModel, when click is performed on recyclerview item

I am new to the Kotlin and I am trying to create an application with MVVM. so what I am trying to do is to make a web call using retrofit in the repository and returning data to the view model and then observing the data from the fragment and as soon as data changes I am notifying it to the recycler view adapter everything is working fine. Now, the problem is I want to update that live data of ViewHolder from the recyclerview. when I click on the CheckBox in recyclerView the data should be updated. But I don't know what is the actual way of doing this.

Here is my ViewHolder.

class MainActivityViewModel : ViewModel() {

private var mutableLiveGitUsers: MutableLiveData<ArrayList<GitUsers>>? = null
private lateinit var gitUsersRepository: GitUsersRepository
var allUsersListener: AllUsersListener? = null

fun init() {

    gitUsersRepository = GitUsersRepository()
    allUsersListener?.onStarted()
    mutableLiveGitUsers = gitUsersRepository.getGitUsers()
    allUsersListener?.onSuccess(mutableLiveGitUsers!!)
}

fun getGitUsersData(): MutableLiveData<ArrayList<GitUsers>>? {
    return mutableLiveGitUsers
}

}

here is how I observe changes in fragment

mutableLiveGitUsers.observe(this, Observer {
        progressBar.hide()
        rvAllUsersAdapter = AllUsersAdapter(mainActivityViewModel.getGitUsersData()?.value!!)
        rvAllUsers.adapter = rvAllUsersAdapter
        rvAllUsersAdapter.notifyDataSetChanged()
    })

RecylerView Adapter

class AllUsersAdapter(private var gitUsersArrayList: ArrayList<GitUsers>) :
RecyclerView.Adapter<AllUsersAdapter.AllUsersViewHolder>() {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AllUsersViewHolder {
    val inflater: LayoutInflater = LayoutInflater.from(parent.context)
    val v: View = inflater.inflate(R.layout.items_all_users, parent, false)
    return AllUsersViewHolder(v)
}

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

override fun onBindViewHolder(holder: AllUsersViewHolder, position: Int) {

    holder.tvUserName.text = gitUsersArrayList[position].login

    Glide.with(holder.itemView.context)
        .load(gitUsersArrayList[position].avatarUrl)
        .centerCrop()
        .into(holder.imageView)

    holder.checkBox.isSelected = gitUsersArrayList.get(position).isSelected

    holder.checkBox.setOnCheckedChangeListener{compoundButton, isChecked ->

        if (isChecked){
    /* Here I want to change the live data so I can observe that changes in my 
fragment and can have an effect in UI*/

            Log.d("TESTC","AllUsersAdapter IsChecked")
        }else{
            Log.d("TESTC","AllUsersAdapter UnChecked")
        }
    }

}

class AllUsersViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

    var tvUserName: TextView = itemView.findViewById(R.id.tvUserName)
    var imageView: ImageView = itemView.findViewById(R.id.imageView)
    var checkBox: CheckBox = itemView.findViewById(R.id.checkBox)
}
}
  1. Introduce an item click callback to your adapter:
class AllUsersAdapter(private var gitUsersArrayList: ArrayList<GitUsers>,
 private val itemClickCallback: ((Boolean) -> Unit)?) :
RecyclerView.Adapter<AllUsersAdapter.AllUsersViewHolder>() {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AllUsersViewHolder {
    val inflater: LayoutInflater = LayoutInflater.from(parent.context)
    val v: View = inflater.inflate(R.layout.items_all_users, parent, false)
    return AllUsersViewHolder(v)
}

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

override fun onBindViewHolder(holder: AllUsersViewHolder, position: Int) {

    holder.tvUserName.text = gitUsersArrayList[position].login

    Glide.with(holder.itemView.context)
        .load(gitUsersArrayList[position].avatarUrl)
        .centerCrop()
        .into(holder.imageView)

    holder.checkBox.isSelected = gitUsersArrayList.get(position).isSelected

    holder.checkBox.setOnCheckedChangeListener{compoundButton, isChecked ->

        if (isChecked){
    /* Here I want to change the live data so I can observe that changes in my 
fragment and can have an effect in UI*/

            Log.d("TESTC","AllUsersAdapter IsChecked")
 itemClickCallback?.invoke(true)
        }else{
            Log.d("TESTC","AllUsersAdapter UnChecked")
 itemClickCallback?.invoke(false)
        }
    }

}

class AllUsersViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

    var tvUserName: TextView = itemView.findViewById(R.id.tvUserName)
    var imageView: ImageView = itemView.findViewById(R.id.imageView)
    var checkBox: CheckBox = itemView.findViewById(R.id.checkBox)
}
}
  1. Handle the click event in your fragment onViewCreated() where you initialise the adapter
 val rvAdapter = AllUsersAdapter(
            gitUsersArrayList = gitUsersArrayList, itemClickCallback = fun(status: Boolean) {
                navController().navigate(
                    viewModel.updateValue(status)
                )
            }
        )

  1. Create the required ViewModel function:
class MainActivityViewModel : ViewModel() {

private var mutableLiveGitUsers: MutableLiveData<ArrayList<GitUsers>>? = null
private lateinit var gitUsersRepository: GitUsersRepository
var allUsersListener: AllUsersListener? = null

fun init() {

    gitUsersRepository = GitUsersRepository()
    allUsersListener?.onStarted()
    mutableLiveGitUsers = gitUsersRepository.getGitUsers()
    allUsersListener?.onSuccess(mutableLiveGitUsers!!)
}

fun getGitUsersData(): MutableLiveData<ArrayList<GitUsers>>? {
    return mutableLiveGitUsers
}

fun updateValue(status: Boolean) {
//@Todo Set new value based on status received
     // mutableLiveGitUsers.value = 
}
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM