current position:Home>Binding adapter of jetpack usage record

Binding adapter of jetpack usage record

2022-01-26 23:49:40 Yuanhao 875

To use data binding, you must be able to use binding adapter , Use binding adapters and kotlin A combination of code can achieve the effect of data binding library , That is, the code is concise . If some logic I can in xml It's defined in , With one line of code, you can , In this way, not only the reusability is high, but also the overall simplicity of the code is greatly improved , Of course, this part is also difficult to understand , Especially when something goes wrong, it's not easy to find .

Preface

In fact, the event processing mentioned above and some of our commonly used feature values, such as TextView Of text It's all about this , Therefore, it is necessary to understand the principle and use . So now the data binding library provides 3 A method of setting property values and processing logic .

Automatic selection method

It's easy to understand , That is, the eigenvalue in the view code is through setXXX To set its value . For example, a property value is example, Then the library automatically attempts to find methods that accept compatible types as parameters setExample(arg), The search method mainly depends on the feature name and type .

Another example of official documents , such as :

android:text="@{user.name}"

expression , The library will look up and accept user.getName() Of the returned type setText(arg) Method , If user.getName() The return type of does not have , Can't find .

In conclusion , Automatic selection method , According to the characteristic value setter Method to find the corresponding function .

Specify a custom method name

The automatic selection method of characteristic value mentioned above , There must be a name that matches setter Method , It can be called successfully , But many attributes don't exist at all , At this point, a property value can be associated with an existing method .

such as android:tint The properties are and setImageTintList The associated , Rather than setTint Method Association , So here we use @BindingMethods To specify the method name for the property value :

@BindingMethods(value = [
        BindingMethod(
            type = android.widget.ImageView::class,
            attribute = "android:tint",
            method = "setImageTintList")])
 Copy code 

In this case , stay ImageView In the view , Use tint, Can automatically call setImageTintList Method to set its value .

About this , In fact, in the data binding library , A lot of this conversion has been done for us , It is convenient for us to use in daily development , such as TextView, The system has provided us with the following BindingMethod 了 :

@BindingMethods({
        @BindingMethod(type = TextView.class, attribute = "android:autoLink", method = "setAutoLinkMask"),
        @BindingMethod(type = TextView.class, attribute = "android:drawablePadding", method = "setCompoundDrawablePadding"),
        @BindingMethod(type = TextView.class, attribute = "android:editorExtras", method = "setInputExtras"),
        @BindingMethod(type = TextView.class, attribute = "android:inputType", method = "setRawInputType"),
        @BindingMethod(type = TextView.class, attribute = "android:scrollHorizontally", method = "setHorizontallyScrolling"),
        @BindingMethod(type = TextView.class, attribute = "android:textAllCaps", method = "setAllCaps"),
        @BindingMethod(type = TextView.class, attribute = "android:textColorHighlight", method = "setHighlightColor"),
        @BindingMethod(type = TextView.class, attribute = "android:textColorHint", method = "setHintTextColor"),
        @BindingMethod(type = TextView.class, attribute = "android:textColorLink", method = "setLinkTextColor"),
        @BindingMethod(type = TextView.class, attribute = "android:onEditorAction", method = "setOnEditorActionListener"),
})
 Copy code 

Provide custom logic ,BindingAdapter

Further extend the above logic , Through the top BindingMethod You can only associate attributes with methods in the view , Now I want to customize the attribute values and methods , I have to define several , To do that , Binding adapter BindingAdapter It's time to use .

Let's look at the official example first , Now I want to set the view paddingLeft, But there is no ready-made setPaddingLeft Method , Only setPadding Method setting 4 In one direction padding, That's direct use BindingAdapter hold paddingLeft Property and a custom method :

@BindingAdapter("android:paddingLeft")
    fun setPaddingLeft(view: View, padding: Int) {
        view.setPadding(padding,
                    view.getPaddingTop(),
                    view.getPaddingRight(),
                    view.getPaddingBottom())
    }
 Copy code 

There is another classic official example , Is to set the picture url, We use this a lot , At the same time, it still involves 2 Property values , We are directly in the xml Middle feeding ImageView Set up imageUrl and error 2 Property values , Then get this in the code 2 The value corresponding to a property value , Right again ImageView Do the processing , The code is :

 @BindingAdapter("imageUrl", "error")
    fun loadImage(view: ImageView, url: String, error: Drawable) {
        Picasso.get().load(url).error(error).into(view)
    }
 Copy code 

Okay , That's all for the official example , Note the parameters here , The first is what you need to set View, Then there is the value .

There's another problem , Is multiple property values , And in the method, I have specified the parameter type of the characteristic value in the method , Like the one above url yes String,error yes Drawable, And when xml When all the conditions are met , Will call , Is there any way to call it with incomplete parameters , Namely requireAll The flag bit is set to false, That is to say, incomplete requirements mean , Look directly at the official example code :

  @BindingAdapter(value = ["imageUrl", "placeholder"], requireAll = false)
    fun setImageUrl(imageView: ImageView, url: String?, placeHolder: Drawable?) {
        if (url == null) {
            imageView.setImageDrawable(placeholder);
        } else {
            MyImageLoader.loadInto(imageView, url, placeholder);
        }
    }
 Copy code 

Extension part

The above has basically finished some of the simplest and most commonly used , In this section, we can talk about some extensions and optimizations . The first is Kotlin The expansion function of language is really delicious , It can greatly improve the simplicity of code , For example, I'm for all View Property values that can be set , That's right View Expand , Yes EditText The characteristic value of , That's right EditText Expand , It is convenient and easy to find , For example, an example in this project :

@BindingAdapter(value = ["afterTextChanged"])
fun EditText.afterTextChanged(action: () -> Unit){
  this.addTextChangedListener(object : TextWatcher{
      override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
      }

      override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
      }

      override fun afterTextChanged(s: Editable?) {
          action()
      }
  })
}
 Copy code 

This code can be written directly in EditTextKt In file .

Another extension is the use of higher-order functions , This is very unskilled in use , It needs to be strengthened later , For example, the login box I need to be in EditText After the content is changed, judge whether it is empty or whether it conforms to the regularity, etc , It's here afterTextChanged Add a callback to , So here we can define a action The higher-order function of , Just like in the example code above .

summary

For the sake of simplicity and readability , Data binding must be able to use , And for complex logic, use binding adapters , It simplifies the code .

copyright notice
author[Yuanhao 875],Please bring the original link to reprint, thank you.
https://en.cdmana.com/2022/01/202201262349362774.html

Random recommended