46

I am quite new in Android Data Binding. I am following this tutorial: Data Binding Library. I am trying to do an adapter that receive multiple parameters. This is my code:

XML

   <ImageView
            android:layout_width="@dimen/place_holder_size"
            android:layout_height="@dimen/place_holder_size"
            android:layout_alignParentRight="true"
            android:layout_alignParentTop="true"
            android:layout_centerVertical="true"
            app:url="@{image.imageUrl}"
            app:size="@{@dimen/place_holder_size}"
            />

BINDING ADAPTER CLASS

public class ViewBindingAdapters extends BaseObservable {

@BindingAdapter({"bind:url", "bind:size"})
public static void loadImage(ImageView imageView, String url, int size) {
    if (!Strings.isNullOrEmpty(url)) {
        Picasso.with(imageView.getContext()).load(url).resize(size, size).centerCrop().into(imageView);
    }
}
....


}

But I am getting this error:

java.lang.RuntimeException: Found data binding errors. ****/ data binding error ****msg:Cannot find the setter for attribute 'app:url' with parameter type java.lang.String on android.widget.ImageView. file:... li_image_item.xml loc:30:27 - 30:40 ****\ data binding error ****

Does anybody know why??

Thanks in advance!

7
  • what is the datatype of image.imageUrl? Commented Dec 6, 2016 at 11:31
  • It is a string. Commented Dec 6, 2016 at 11:32
  • "bind:url", "bind:size" != app:url, app:size Commented Dec 6, 2016 at 11:32
  • 1
    In the tutorial they do it like this, in the paragraph: Custom Setters. Commented Dec 6, 2016 at 11:35
  • 1
    yes indeed: '''Custom namespaces are ignored during matching''', is image.imageUrl a String? Commented Dec 6, 2016 at 11:37

6 Answers 6

61

Problem is @dimen/place_holder_size, it returns float while you are catching it as int

change you BindingAdapter method to this

@BindingAdapter({"bind:url", "bind:size"})
public static void loadImage(ImageView imageView, String url, float size) {

}

you can refer this

Sign up to request clarification or add additional context in comments.

1 Comment

If i set change url value then it calls this method and when i set size value then this method is called again. Is there any way that it calls only once when both values are set
25

What I did wrong is the order of the arguments in the function. You can add multiple attributes in Binding Adapter, but they should match the arguments with the same sequence defined in the method.

Here is my code snippet for Kotlin

@BindingAdapter(value = ["bind:brand", "bind:model", "bind:age"], requireAll = false)
@JvmStatic
fun bindProductDetails(linearLayout: LinearLayout, brand: String?, model: String?, age: String?) {
    if (brand != null && !brand.isEmpty()) {
        //code
        //code

    }
}

Comments

10

try this

 @BindingAdapter(value={"url", "size"}, requireAll=false)
 public static void loadImage(ImageView imageView, String url, int size) {
        if (!Strings.isNullOrEmpty(url)) {
            Picasso.with(imageView.getContext()).load(url).resize(size, size).centerCrop().into(imageView);
        }
    }

1 Comment

just clean and rebuild project bcoz sometime studio not update it still it not work try it with invalid catches or restart ur IDE(may be stupid bt it works sometime)
6

Apart from the example provided above by @Kishan Solanki, And with changes happening in the Data Binding library, all you need is to declare them with comma separated values. Example

@BindingAdapter("loadImageFrom", "widthDp")
fun loadImages(imageView: ImageView, url: String?, widthDp: Int) {
    url?.let {

        val height = (widthDp / 3) * 4
        val fullUrl = getImagePosterUrl(url)
        Picasso.get().load(fullUrl).resize(widthDp.px, height.px).into(imageView)
    }

}

Bu the most important thing to remember is that you provide the data to the adapter attributes, in the DataBinding format.

example to provide Int as parameter in XML you have to write

app:widthDp="@{120}"

which is

app:your_attribute="@{your_data}"

P. S. - Oh and one more thing, widthDp**.px** is an extension function which converts Int of a dp value to relevant pixels value based on screen density. So don't get confused.

Comments

5

Update

You don't need to create prefix bind:, just use this.

@BindingAdapter({"url", "size"})
public static void loadImage(ImageView imageView, String url, float size) {

}

In xml use any prefix like app:

app:url="@{image.imageUrl}"

Comments

5

See https://developer.android.com/topic/libraries/data-binding/binding-adapters.

@BindingAdapter("imageUrl", "placeholder", requireAll = false)
fun ImageView.setImageUrl(url: String?, placeHolder: Drawable?) {
    if (url == null) {
        setImageDrawable(placeholder)
    } else {
        MyImageLoader.loadInto(this, url, placeholder)
    }
}

Note that BindingAdapter attributes and setImageUrl parameters may have different names. But they should go in the same order. If some of these attributes are defined in XML (in this example it is ImageView), this method will be called.

<ImageView 
    app:imageUrl="@{venue.imageUrl}"
    app:placeholder="@{@drawable/venueError}" />

Attributes should have the same types as defined in the method. You can also use listeners. Instead of Kotlin lambdas use interfaces.

This class should be put in the same module with XML. Otherwise you will get an error like AAPT: error: attribute imageUrl (aka com.example.imageUrl) not found..

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.