Data binding: set property if it isn't null
Asked Answered
H

4

65

Cannot understand... How to set some property of view only if variable field isn't null?
For example

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

    <data>
        <variable
            name="item"
            type="com.test.app.Item" />
    </data>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:orientation="horizontal">

        <ImageView
            android:id="@+id/icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:layout_centerVertical="true"
            android:layout_margin="16dp"
            android:src="@{item.getDrawable()}"/>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginEnd="16dp"
            android:layout_marginLeft="72dp"
            android:layout_marginRight="16dp"
            android:layout_marginStart="72dp"
            android:layout_toLeftOf="@id/action"
            android:layout_toStartOf="@id/action"
            android:orientation="vertical">

            <TextView
                android:id="@+id/text1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:singleLine="true"
                android:textColor="@color/black_87"
                android:textSize="16sp"
                android:text="@{item.getTitle()}"/>

            <TextView
                android:id="@+id/text2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:autoLink="web|email"
                android:linksClickable="false"
                android:singleLine="true"
                android:textColor="@color/black_54"
                android:textSize="14sp"
                android:text="@{item.getSubtitle()}"/>


        </LinearLayout>

    </RelativeLayout>
</layout>

Some field of Item can be null and I won't call methods of layout views unnecessarily. And I won't get NullPointerException. How can I set property only if it isn't null?
P.S. Sorry for English.

Heilman answered 25/3, 2016 at 20:4 Comment(1)
As mentioned by @Khemraj, you don't have to check values nullability unless you want to set some special values for the nullable case. Data binding expressions provides this for you for freeAguilera
I
195

Well data binding avoids NullPointerException in general by checking for it and assigns the default value (null for example) even if item itself is null in your example.

But a basic example for null checks for the item's properties:

android:text='@{item.title != null ? user.title : ""}'

Or use the "Null Coalescing Operator". The null coalescing operator (??) chooses the left operand if it is not null or the right if it is null.

android:text='@{item.title ?? ""}'

Note that title or getTitle doesn't matter.

Indeterminate answered 25/3, 2016 at 20:21 Comment(9)
I know it. As I understood it's impossible to not call method in View if value is null?.Heilman
I'm sorry I'm not sure what you are asking here. Are you trying to keep the previous value if the new value was null? Not sure this is a good way of accomplishing that through data binding. The new two-way data binding could be used I guess by setting the value of some (possibly other) object whenever it is not null. But I doubt this is a good way of going about it.Indeterminate
One way would be to split up the variable used instead, have one for each property instead. Of type String instead of Item.Indeterminate
Thank you! I think it is a single possible variant in my case. Just I have icon that can be null (adapter can not use this icon and mark it as GONE, so I don't need to set it any value (any Drawable) because it's invisible all same).Heilman
Should work fine, and use data binding for the visibility as well! android:visibility="@{item.drawable == null ? View.INVISIBLE : View.VISIBLE}" You would need to add an import for View inside the data element though: <import type="android.view.View"/>Indeterminate
Just it gives error when I set null drawable in ImageView. I said my adapter can use this icon for one item and not use for second. Sorry, it may be I cannot explain it clearly in English. I like idea to split values so I can control visibility and drawable separately.Heilman
Aah ImageView doesn't like null there. Suggest setting it to an empty or transparent drawable on null then.Indeterminate
how to do this work? ''' android:visibility = @{user.nick != "" ? View.Visibile : View.Gone'''Chiropractic
what if item itself is Nullable type val item : Item? = nullCotyledon
K
26

Data binding does not need to check for null value, it will be handled by binding class.

If you need to check null for other purpose (like setting default value) then you can use like this.

android:text='@{item.gender != null ? item.gender : @string/male}'

or

android:text='@{item.gender ?? @string/male}'

Both above examples are same. Here @string/male is default value, when item.gender is null.

Keller answered 9/8, 2018 at 8:58 Comment(0)
H
8

I tried something like this.

<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">

  <data>
     <import type="android.text.TextUtils"/>
     <variable
        name="mOrder"
        type="com.test.app.models.Order" />
  </data>
  <TextView
    android:id="@+id/mLblSource"
    android:layout_width="100dp"
    android:layout_height="40dp"
    android:layout_marginTop="8dp"
    android:layout_marginEnd="8dp"
    android:text='@{TextUtils.isEmpty(mOrder.order_id) ? "- -" : mOrder.order_id}'
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintBottom_toBottomOf="parent" />
</layout>
Huysmans answered 18/2, 2021 at 15:41 Comment(0)
H
0
<import type="android.view.View"/>
android:visibility="@{UserDetails == null ? View.INVISIBLE : View.VISIBLE}"

Import View first

Hydromancy answered 26/4 at 9:13 Comment(1)
Thank you for your interest in contributing to the Stack Overflow community. This question already has a few answers—including one that has been extensively validated by the community. Are you certain your approach hasn’t been given previously? If so, it would be useful to explain how your approach is different, under what circumstances your approach might be preferred, and/or why you think the previous answers aren’t sufficient. Can you kindly edit your answer to offer an explanation?Littlest

© 2022 - 2024 — McMap. All rights reserved.