1

I can do this programatically, but i want to know best approach using android databinding.

Here is my xml layout. I want to increase or decrease int value onClick of some button. I don't want handle click in activity class. Is this possible, if yes.

In below layout you can see an Integer value count. Value count should be changed on click of Button.

<?xml version="1.0" encoding="utf-8"?>
<layout
    xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

        <import type="android.view.View"/>

        <variable
            name="activity"
            type="com.amelio.ui.activities.ActivityProductDetail"/>

        <variable
            name="count"
            type="Integer"/>
    </data>

    <LinearLayout
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        >

        <Button
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:onClick="@{() -> count++}"
            android:text="Less"
            />

        <TextView
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:text="@{`` + count}"
            />

        <Button
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:id="@+id/ivBtnPlus"
            android:onClick="@{() -> count--}"
            android:text="Add"
            />
    </LinearLayout>
</layout>
Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
Khemraj Sharma
  • 57,232
  • 27
  • 203
  • 212
  • You don't say or show how count would be used other than to update the textView. Surely you don't want a user click to have no effect other than to update a click count. I appreciate that you probably simplified the example to pose the question, but to really answer it, it would probably be better if you gave a clearer example of what you are really trying to accomplish because if the logic in xml was for presention only, it might be ok, otherwise, I agree with @aaroncio. – Alan Todtenkopf May 09 '18 at 15:43
  • I'll use it as cart product count. If this is solved, i will implement as per my need. count variable is inside my model class, and i will save that model in my database. – Khemraj Sharma May 09 '18 at 15:50
  • I don't think there is need of my model class and activity code. so i posted only needy thing. – Khemraj Sharma May 09 '18 at 15:50
  • it doesn't look that way. I would expect variable to be something like `com.amelio.model` and binding `android:onClick="@{() -> model.count++}"`. And in that case, it would be better (and more conventional) for reasons stated by @aaroncio to handle the incrementing in the model. – Alan Todtenkopf May 09 '18 at 16:08
  • It is same like you said, I simplified so i don't have to post unnecessary classes. Okay so we can not change a Integer directly like this? I would have to make methods in class like activity. – Khemraj Sharma May 09 '18 at 16:09
  • You can, it's just not the best practice. Not only is it less testable as @aaroncio pointed out, you are mixing state and behavior which can create complications. For example, say when cart count changes, you want to save new count to DB. You can do this in the setter for `count` but now, what happens when you are initializing count from what is in database? You could end up with writing back to database. And if you update count each time DB is written, you could have inifinite loop. You can prevent by checking for real changes, etc, but would be better to have method `IncreaseCount` – Alan Todtenkopf May 09 '18 at 16:52
  • Cool, i looked for this because my db does not look for real time changes. I put model in db on a button click (it will not get looping). I got that it is not best practice. I was just curious how it is done in this way. I have already made two methods for now. Asked just because i should at least know the way. – Khemraj Sharma May 09 '18 at 16:56

1 Answers1

1

It will depend on what you are trying to achieve, if you want to make your code more testable, I'd suggest that you handle the click in the XML which will call a function in your Activity or other class where you can test the behavior of this function and if you need to add more complex logic like data validation, database storage, etc, it will be better. In the end the view should be dummy and it allows you to reuse the code as in the case that other function handle it.

Also having a bunch of logic in the XML is a bad practice which will make your code unmaintainable. I'd suggest you to read about the MVVM pattern and data binding Android MVVM Design Pattern

Try this:

<Button
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:onClick="@{() -> activity.myCountMethod()}"
        android:text="Less"
        />

In Activity you must implement myCountMethod(), if you don't want to have in your activity you can add another variable with the class that you want like:

<data>

    <import type="android.view.View"/>

    <variable
        name="activity"
        type="com.amelio.ui.activities.ActivityProductDetail"/>
    <-- Add OtherClass -->
    <variable
        name="otherClass"
        type="com.amelio.ui.activities.OtherClass"/>

    <variable
        name="count"
        type="Integer"/>
</data>


<Button
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:onClick="@{() -> otherClass.myCountMethod()}"
        android:text="Less"
        />

You can find more info here:

https://developer.android.com/topic/libraries/data-binding/expressions#listener_bindings

aaroncio
  • 307
  • 1
  • 6