Trying to use the new Android Data Binding in my project, but I'm getting an error when trying to set the 'android:tag' property to some custom variable.
My menu_item.xml file:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="menuItem"
type="com.example.MenuItem" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:tag="@{menuItem}"
tools:ignore="UseCompoundDrawables">
<!--suppress AndroidUnknownAttribute -->
<ImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:imageResource="@{menuItem.itemType.drawableId}" />
<TextView
android:id="@+id/displayName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{menuItem.itemType.displayNameId}" />
</LinearLayout>
</layout>
My MenuItem class:
public class MenuItem {
public final ItemType itemType;
public MenuItem(ItemType itemType) {
this.itemType = itemType;
}
}
Part of the genetated MenyItemBinding.java:
public MenuItemBinding(View root) {
super(root, 0);
final Object[] bindings = mapBindings(root, 3, sIncludes, sViewsWithIds);
this.displayName = (android.widget.TextView) bindings[2];
this.displayName.setTag(null);
this.icon = (android.widget.ImageView) bindings[1];
this.icon.setTag(null);
this.mboundView0 = (android.widget.LinearLayout) bindings[0];
this.mboundView0.setTag(root.getResources().getString(com.myApp.R.string.@{menuItem}));
setRootTag(root);
invalidateAll();
}
And the error is in the generated class, when trying to set the Tag of the bound view.
Any ideas how to get around this? Preferably, not to use a custom LinearLayout to support this.
View binding and data binding both generate binding classes that you can use to reference views directly. However, view binding is intended to handle simpler use cases and provides the following benefits over data binding: Faster compilation: View binding requires no annotation processing, so compile times are faster.
Recently Android has announced that with Kotlin 1.4. 20, their Android Kotlin Extensions Gradle plugin will be deprecated and will no longer be shipped in the future Kotlin releases. Android Kotlin Extensions plugin brought with it two very cool features : Synthetics let you replace calls to findViewById with kotlinx.
That is a bug. We haven't tried data binding tags, mostly because tags are special.
When targeting devices pre-ICS, Android data binding takes over the tag of the outermost element of the layout. This tag is used for mostly for binding lifecycle and is used by DataBindingUtil.findBinding()
and DataBindingUtil.getBinding()
.
So, since data binding isn't working on tags, the only work-around is to not supply a tag to your LinearLayout or supply a fixed tag or resource string. If you are targeting ICS and above, it is valid to reassign the tag after binding the layout:
MenuItemBinding binding = MenuItemBinding.inflate(layoutInflater);
binding.getRoot().setTag(menuItem);
You can also create a BindingAdapter for a new attribute:
@BindingAdapter("specialTag")
public static void setSpecialTag(View view, Object value) {
view.setTag(value);
}
and then use it in your layout:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
app:specialTag="@{menuItem}"
tools:ignore="UseCompoundDrawables"/>
This will allow you to use findViewByTag()
and all of the other things you expect.
However, this will NOT work if you target Honeycomb and earlier devices. There is no getting around that. You may be tempted to do something like this:
@BindingAdapter("specialTag")
public static void setSpecialTag(View view, Object value) {
view.setTag(R.id.app_tag, value);
}
You won't be able to use findViewByTag
with that approach, but it will store whatever value you want when you use your view. But the reason we don't use ID'd tags with Honeycomb and earlier is that there is a memory leak when using ID'd tags, so don't do it.
I hope this helps. I'll file a bug internally to support data bound android:tags.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With