Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the use of binding adapter in Android?

I have been reading articles about binding adapter in Android, but I don't seem to understand it. When is a binding adapter used? Can someone explain it with a simple example?

An article I read had a binding adapter in the Main Activity. The binding Adapter had a parameter "toastMessage", and apparently, the method annotated with this binding adapter was said to be called whenever the "toastMessage" (which was an attribute in viewModel class) changed.

I don't understand why we need to do this.

An explanation with a simple example would help a lot.

Thanks!

like image 425
Spires Avatar asked May 25 '19 14:05

Spires


People also ask

What is the use of Data Binding in Android?

The Data Binding Library is a support library that allows you to bind UI components in your layouts to data sources in your app using a declarative format rather than programmatically.

What is the advantage of view binding in Android?

View binding allows a developer to incorporate significant interaction in an application. This concept seeks to eliminate the findViewById keyword. Removing such boilerplate code allows developers to be more productive. A binding class is usually generated for each layout file when using view binding.


2 Answers

Binding Adapters are used to have custom setters to some property of your views. The most common use case I can think of is setting an image to an ImageView, where loading of image is mostly done off the UI thread.

Most of us have our preferred image loading library to load images. For every image you would want to load you would write code to load the url from remote (or local) and set it to our image view. You could of course have some utility method once you see this boilerplate in every place you have an image view.

Binding adapters makes this a little more simpler. You set the attribute in XML and data binding library will look for the binding adapter to set that property to your view. Since the data is an observable changes will be triggered to the view whenever the data changes.

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:imageUrl="@{data.imageUrl}"/>
@BindingAdapter("imageUrl")
public static void setImageUrl(ImageView imageView, String url) {
    if (url == null) {
        imageView.setImageDrawable(null);
    } else {
        Picasso.get().load(url).into(imageView); // replace with your fav image loading lib
    }
}

The doc provides several such examples where you would want to use this. This article by George Mount also explains it very clearly where and why you may want to use this if you are using data binding.

like image 116
Arka Prava Basu Avatar answered Sep 23 '22 00:09

Arka Prava Basu


Binding adapters are responsible for making the appropriate framework calls to set values.

When you're using data binding into your application, setting values into your views is a normal thing. Like below example:

 <ProgressBar
         app:layout_constraintLeft_toLeftOf="parent"
         app:layout_constraintRight_toRightOf="parent"
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintBottom_toBottomOf="parent"
         android:visibility="@{viewmodel.loadingData?View.VISIBLE:View.GONE}"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"/>

But some times you want to do something special in your setting methods. For example, you have a RecyclerView in your XML and you want to define its adapter, You can do it by defining it via a bindingAdapter in your code for it.

<android.support.v7.widget.RecyclerView
            android:id="@+id/rv_main_articles"
            app:adapter="@{viewmodel.articles}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            android:layout_width="0dp"
            android:layout_height="0dp"/>

There are mostly two usages of binding adapters:

1- For RecyclerView:

@JvmStatic
        @BindingAdapter("app:adapter")
        fun <T> setItems(recyclerView: RecyclerView, items: List<T>?) {

            Log.d(TAG, "articles:[$items]")

            if (recyclerView.adapter is HomeAdapter) {

                if (items != null) {
                    (recyclerView.adapter as HomeAdapter).swapData(items)
                }

            }
        }

2- For loading images into your ImageView(s)

@JvmStatic
        @BindingAdapter("app:loadImage")
        fun setImageResource(view: ImageView, imageUrl: String?) {

            val context = view.context

            val options = RequestOptions()
                .diskCacheStrategy(DiskCacheStrategy.RESOURCE)


            imageUrl?.let {

                Glide.with(context)
                    .setDefaultRequestOptions(options)
                    .load(imageUrl)
                    .transition(DrawableTransitionOptions.withCrossFade(1000))
                    .into(view)
            }
        }

More info : link

like image 31
Ehsan Avatar answered Sep 22 '22 00:09

Ehsan