Search code examples
androidandroid-fragmentskotlinadapter

How to send data from Adapter to ViewModel to Fragment


My structure is like this, in the Fragment I call the ViewModel which instantiate the Adapter

For each item of my RecyclerView, I have a button which I listen

binding.addItem.setOnClickListener(onAddItemClicked(product))

private fun onAddToQuoteClicked(product: Product): View.OnClickListener {
    return View.OnClickListener {
        // TODO add item
    }
}

I don't know how to send this item data to the fragment, is there a way to do that?

Should I use interface between Adapter and ViewModel and between ViewModel and Fragment ?

Or Can I use RxEvent & RxBus ?


Solution

  • First for navigation between ViewModel and Fragment -

    • you can use RxJava PublishSubject make it public and subscribe to it in your Fragment which can use public methods of ViewModel.
    • or you can use an interface, better in my opinion as using interface you are using simpler logic, much less errors in that case, and also it is more clean code as you can name methods in interface as you want - easier to read.

    Second for communication between Adapter and Fragment - you can use same strategy as described above. In that case I recommend to use RxJava, as usually you would just need to handle one or few click listeners (so it is for example for observable which emits some data object).
    If you need some code examples text me in comments.

    UPDATE - it is better practice to create your Adapter instance in View, as I assume you are using MVVM design pattern (where all UI related code must be located in View component).

    Example Fragment - Adapter communication Rx - PublishSubject
    In your Adapter

         private val publisher = PublishSubject.create<Product>()
    fun getObservableProductItem(): Observable<Product> = publisher.hide()
    
    binding.addItem.setOnClickListener(onAddItemClicked(product))
    private fun onAddToQuoteClicked(product: Product): View.OnClickListener {
        return View.OnClickListener {
            publisherRideItem.onNext(items[adapterPosition])
        }
    }
    
    override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
        publisherRideItem.onComplete()
    }
    

    And in your Fragment

     compositeDisposable.add(adapter.getObservableProductItem().subscribe {
                //TODO do whatever you want with it
            })   
    
      override fun onDestroy() {
        super.onDestroy()
        compositeDisposable.clear()
    }