3

I want to make onClick() in my layout xml trigger two methods from two viewmodels.

Code:

<Button
    android:onClick="@{() -> model.onButtonClick()}"
    ... />

The above code calls one method, I want it to call another one in from a different viewmodel.
Function call I want to add: model2.onButtonClick()

Is it possible? If yes, kindly add an minimal example. (Expecting a xml solution)

Note: Viewmodels are passed as arguments in xml. (data-binding variables)

Edit 1: Both functions are in two different view models. So I (after some research) know that using/declaring/initializing one view model inside another is not a good practise.

I could create a click listener inside my fragment and call both functions there. But I want to eliminate click listener in fragments (views as per MVVM).

I am not looking for some possible way. I am searching for a best practise method, where I intend to implement MVVM, seperation of concerns and data-binding.

Abhimanyu
  • 11,351
  • 7
  • 51
  • 121

5 Answers5

5

I've found solution. Maybe stupid but genius in the simplicity:

app:onRefreshListener="@{() -> dashboardVM.onRefresh() != homeVM.onRefresh()}"

method needs to return true/false -> no matter.

For any other number of methods use OR and return always false.

Correct solution shall be implemented via converter. But it takes a lot of code.

user2239604
  • 71
  • 2
  • 7
1

You have two options,

  1. Call the second method in the first method.
fun method1() {
//do stuff 
method2() 
} 
fun method2() {
//do more stuff
} 
  1. In case you don't want to mess up your existing code structure, Create a separate function that calls the two functions.
fun onClickMethod () {
method1() 
method2() 
} 
fun method1() {
//do stuff  
} 
fun method2() {
//do stuff
} 
Chrisvin Jem
  • 3,940
  • 1
  • 8
  • 24
  • You could try to set up a basic subscriber model, wherein the viewmodels subscribe their function to be called on a button onClick. I've never done that before, but I've seen a colleague set up something similar before. Not sure if it's a good practice or not though. – Chrisvin Jem Jul 14 '19 at 05:14
0

In your xml import two view models and pass them as params in your custom method which will call each method from the view models.

I have never try that before but it should work. Let me know if you don't understand

Edhar Khimich
  • 1,468
  • 1
  • 17
  • 20
0

Using a Higher-order function we can achieve trigger two methods at the same time

  <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
    
        <data>
    
            <import type="android.view.View" />
    
            <variable
                name="cartViewModel"
                type="com.rizek.android.users.ui.cart.CartViewModel" />
    
            <variable
                name="product"
                type="com.rizek.android.users.model.productlist.Product" />
    
            <variable
                name="productInteractionListener"
                type="com.rizek.android.users.adapters.recyclerview.cart.ProductListAdapter.ProductInteractionListener" />
        </data>
    
        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
            <TextView
                style="@style/text_medium"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:drawablePadding="8dp"
                android:onClick="@{()->
                productInteractionListener.onItemStateChanged(product,cartViewModel.addProduct(product))
                }"
                android:padding="8dp"
                android:text="Add to basket"
                android:textColor="@color/blue"
                android:textSize="14sp"
                app:drawableStartCompat="@drawable/ic_add_circle"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />
    
        </androidx.constraintlayout.widget.ConstraintLayout>
    </layout>

ProductInteractionListener

interface ProductInteractionListener {
           fun onItemStateChanged(product: Product, action: () -> Unit)
        }
Arunachalam k
  • 734
  • 1
  • 7
  • 20
0

This work for me:

<Button
    android:onClick="@{() -> model.onButtonClick() ? model2.onButtonClick() : void}"
    ... />

In fun onButtonClick() you must return True. From Google developer

Eneka
  • 1
  • 1