title: Update data from one element in RecyclerView using ViewModel and LiveData
body: <p>I am trying to write an app using a variety of architectural components/concepts and are now at a point where I am not sure what the best/preferred solution to one of my problems is.</p>
  <p>I have a fragment inside the app that has a RecyclerView and displays elements from the Database in a List. Each item has a delete and an edit button. Now I have to implement those functionalities, but I am a bit at a loss on how to do this.
  I can either update the database and listen for changes there to update the RecyclerView or i can update the RecyclerView first and update the Database when the fragment is destroyed/paused. But I am struggling to implement either of those approaches.</p>
  <p>The view needs to be updated when the element has either been changed (display new title etc.) or been removed from the list. If I put the onClickListener inside the ViewHolder, I don't have access to the complete dataset. If I put it inside onCreateViewHolder I don't have access to the item that was clicked. And in OnBindViewHolder I don't have access to the button.</p>
  <p>In the onClickListener I either need to change the data the RecycleViewer is displaying (and update the database when the Fragment is destroyed/paused) or directly call the method in the ViewModel that accesses the database. I also don't know how to access the ViewModel and its methods from the Adapter (maybe this shouldn't be done in general) as ViewModelProvider(?)[PlacesViewModel::class.java] needs a ViewModelStoreOwner or a ViewModelStore and I don't really understand either one or how to access them from the Adapter.</p>
  <p>What am I missing? What is the best/proper way to do this? It might be something very obvious, but in between all of those new concepts I feel a bit lost. As I said, I am new to Android and only started using most of the concepts here (LiveData, ViewModel etc.). It is possible that I am not using them properly and the whole approach is not correct.</p>
  <p>Here is the fragment:</p>
  <pre><code>class PlacesFragment : Fragment() {
  
      private var _binding: FragmentPlacesBinding? = null
      private val binding get(): FragmentPlacesBinding = _binding!!
      private lateinit var mViewModel: PlacesViewModel
  
      override fun onCreate(savedInstanceState: Bundle?) {
          super.onCreate(savedInstanceState)
          mViewModel = ViewModelProvider(this)[PlacesViewModel::class.java]
      }
  
      override fun onCreateView(
          inflater: LayoutInflater, container: ViewGroup?,
          savedInstanceState: Bundle?
      ): View {
          // Inflate the layout for this fragment
          _binding = FragmentPlacesBinding.inflate(inflater, container, false)
  
          // set the adapter for the recyclerview to display the list items
          val recyclerView = _binding!!.recyclerViewPlaces
          mViewModel.places.observe(viewLifecycleOwner){ places -&gt;
              recyclerView.adapter = RecyclerViewPlacesAdapter(places)
          }
  
          return binding.root
      }
  
      override fun onDestroyView() {
          super.onDestroyView()
          _binding = null
      }
  }
  </code></pre>
  <p>the ViewModel:</p>
  <pre><code>class PlacesViewModel(app: Application): AndroidViewModel(app) {
  
      private var _places: MutableLiveData&lt;MutableList&lt;Place&gt;&gt; = MutableLiveData()
      val places get() = _places
  
      init {
          viewModelScope.launch {
              try{
                  val db = AppDatabase.getInstance(getApplication())
                  _places.value = db.placeDao().getAll().toMutableList()
              } catch(e: Exception){
                  Log.e(&quot;Error&quot;, e.stackTraceToString())
              }
          }
      }
  
      fun deletePlace(place: Place){
          viewModelScope.launch {
              try{
                  val db = AppDatabase.getInstance(getApplication())
                  _places.value?.remove(place)
                  //db.placeDao().delete(place)
              } catch(e: Exception){
                  Log.e(&quot;Error&quot;, e.stackTraceToString())
              }
          }
      }
  }
  </code></pre>
  <p>and the adapter:</p>
  <pre><code>class RecyclerViewPlacesAdapter(private val dataSet: List&lt;Place&gt;) :
      RecyclerView.Adapter&lt;RecyclerViewPlacesAdapter.ViewHolder&gt;() {
  
      class ViewHolder(itemBinding: ListTilePlacesBinding) : RecyclerView.ViewHolder(itemBinding.root) {
          private val placeTitle: TextView = itemBinding.placeTitle
          private val placeAddress: TextView = itemBinding.placeAddress
          var place: Place? = null
  
          fun setValues(){
              if(place != null){
                  placeTitle.text = place!!.title
                  placeAddress.text = place!!.address //TODO either address or lat/long
              }
          }
  
          init {
              // Define click listener for the ViewHolder's View.
              itemBinding.buttonDelete.setOnClickListener { 
                  // TODO remove item from dataset and in RecyclerView
              }
              itemBinding.buttonEdit.setOnClickListener {
                  // TODO edit item and display changes in RecyclerView
              }
          }
      }
  
      override fun onCreateViewHolder(
          parent: ViewGroup,
          viewType: Int
      ): ViewHolder {
          val itemBinding = ListTilePlacesBinding.inflate(LayoutInflater.from(parent.context), parent, false)
  
          return ViewHolder(itemBinding)
      }
  
      override fun onBindViewHolder(holder: ViewHolder, position: Int) {
          holder.place = dataSet[position]
          holder.setValues()
      }
  
      override fun getItemCount() = dataSet.size
  }
  </code></pre>
  <p><strong>UPDATE:</strong>
  As @cactustictacs suggested, I added a deleteItem() method to the adapter that removed the item from the dataSet and called notifyItemRemoved to update the View. I also passed the ViewModel to the adapter to call its method. I was not sure before if this is a correct approach to just pass it to another Method.</p>