0

I am trying to define an attribute for any view using the Data Binding Library, as explained in this Android Developers post.

To do so, the post says one first needs a layout with an enclosing <layout> tag:

<?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">
    <LinearLayout android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView android:id="@android:id/text1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:attribute='@{"name"}'/>
    </LinearLayout>
</layout>

At this point, the layout caused a ClassNotFoundException when inflated. The only way I found to get rid of it was to add a <data></data> node, even if it was absent from the Android Developers post:

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

(The post does not mention it, but I had to enable dataBinding in my build.gradle as recommended in the Guide before I could build.)

The post then explains how to write a BindingAdapter method to process the attribute:

import android.databinding.BindingAdapter;
import android.util.Log;
import android.view.View;

public class AttributesBindingAdapter {
    @BindingAdapter("bind:attribute")
    public static void bindAttribute(View view, String attributeName){
        Log.e("PLN", attributeName);
    }
}

However, the bindAttribute method is never called. I do see the generated code for the layout in my build folder, but nothing else happens.

Why is my BindingAdapter ignored?

PLNech
  • 3,087
  • 1
  • 23
  • 52
  • 1
    It should be `@BindingAdapter("bind:attribute")` instead of `@BindingAdapter("app:attribute")` , you should refer [this](http://developer.android.com/intl/es/tools/data-binding/guide.html#attribute_setters) – Ravi May 10 '16 at 04:06

3 Answers3

2

I found the solution to my problem, I was not creating the Binding correctly:

Following the first steps of the Guide, I used DataBindingUtil.setContentView, but for ListView items you need to use ItemBinding.inflate in the Adapter's ViewHolder:

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    ViewDataBinding binding = DataBindingUtil.inflate(
            LayoutInflater.from(parent.getContext()),
                    R.layout.item, parent, false);
    return new ViewHolder(binding.getRoot());
}
PLNech
  • 3,087
  • 1
  • 23
  • 52
1

From what I can tell in that first link, the data tag is present. It was probably omitted in the G+ post because its boilerplate. In fact, in the docs it says

Data-binding layout files are slightly different and start with a root tag of layout followed by a data element and a view root element.

Anyways, I think you might be missing some required sugar in the layout file. Can you try:

app:attribute='@{"name"}`

Maybe its required for the binding to occur. I mean right now I am aiming blind until I actually test this. But from that post I see app:imageUrl='@{"http://example.com/image.jpg"}'.

Andy
  • 10,553
  • 21
  • 75
  • 125
  • I agree with you that one should follow the guide and use this data tag, which I did. Still, the problem persists. As for the post you linked, how do you think it could help? The OP has a compile-time error (whereas my app builds and runs but ignores my BindingAdapter), and the accepted solution using `@BindingMethods(@BindingMethod(...))` instead of `@BindingAdapter` still results in the method not being called. Could you be more specific? – PLNech May 09 '16 at 15:27
  • 1
    @PLNech that link I added should be gone. I misunderstood the problem. Adding the `@{}` didn't help? Maybe try adding it exactly as it is in the post. so `app:attribute='@{"name"}'`. – Andy May 09 '16 at 15:29
  • You are probably right about the syntax (and I updated the question to reflect it). However, even with `app:attribute='@{"name"}'` the method is still not called... – PLNech May 09 '16 at 16:13
  • @PLNech what is your layout file called? – Andy May 09 '16 at 16:38
  • `item.xml`(it will be used to display items in a `ListView`) – PLNech May 09 '16 at 17:19
  • Is it possible you aren't using the convention? ` the layout file contact_item.xml will generate ContactItemBinding`. If its not being called its possible that it can't find it since it might expect it in a specific file. – Andy May 09 '16 at 20:04
1

It should be @BindingAdapter("bind:attribute") instead of @BindingAdapter("app:attribute")

and try with this, it might work.

app:attribute="@{`name`}"
Ravi
  • 34,851
  • 21
  • 122
  • 183