1.BindingAdapter介绍
Binding adapters 可以作为一个设置某个值的框架来使用,databinding 库可以允许指定具体的方法来进行相关值的设置,在该方法中可以做一些处理逻辑,Binding adapters 会最终给你想要的结果。Android Databinding框架中已经为我们准备了大部分控件的一些属性的BindingAdapter,就比如TextView:
public class TextViewBindingAdapter {
private static final String TAG = "TextViewBindingAdapters";
public static final int INTEGER = 1;
public static final int SIGNED = 3;
public static final int DECIMAL = 5;
public TextViewBindingAdapter() {
}
@BindingAdapter({"android:text"})
public static void setText(TextView view, CharSequence text) {
CharSequence oldText = view.getText();
if (text != oldText && (text != null || oldText.length() != 0)) {
if (text instanceof Spanned) {
if (text.equals(oldText)) {
return;
}
} else if (!haveContentsChanged(text, oldText)) {
return;
}
view.setText(text);
}
}
当某些属性需要自定义处理逻辑的时候可以使用 BindingAdapter,比如我们可以使用 BindingAdapter 重新定义 TextView 的 setText 方法,让输入的英文全部转换为小写,自定义 TextViewAdapter 如下:
/**
* 自定义BindingAdapters
* Powered by jzman.
* Created on 2018/12/6 0006.
*/
public class TextViewAdapter {
@BindingAdapter("android:text")
public static void setText(TextView view, CharSequence text) {
//省略特殊处理...
String txt = text.toString().toLowerCase();
view.setText(txt);
}
}
此时,当我们使用 databinding 的优先使用我们自己定义的 BindingAdapter,可能会疑惑为什么能够识别呢,在编译期间 data-binding 编译器会查找带有 @BindingAdapter 注解的方法,最终会将自定义的 setter 方法生成到与之对应的 binding 类中。
2. 实现步骤
step1.修改app模块下的build.gradle文件
开启了后DataBinding才会自动生成Adapter类,比如TextViewAdapter。
dataBinding {
enabled = true
}
step2.修改activity_main.xml布局文件
<?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"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="imageUrl"
type="String" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ImageView
app:imageUrl="@{imageUrl}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
step3.添加Picasso依赖
添加方法,点击File>Project Structrue>Dependencies。点All Dependencies下面的+,选择1.Library Dependency。
弹出Add Library Dependency窗口,在窗口中的Step1下面的文本框中输入picasso。点击搜索。这里可能花费的时间比较久, 最后搜索到了选中Square 公司开源的Android 端的图片加载和缓存框架com.squareup.picasso。
step4.创建ImageViewBindingAdapter类。
注意@BindingAdapter()中的属性名称和前面布局文件中定义的变量名称一致。
package com.gaoting.imageviewbindingadapter;
import android.widget.ImageView;
import androidx.databinding.BindingAdapter;
import com.squareup.picasso.Picasso;
public class ImageViewBindingAdapter {
@BindingAdapter("imageUrl")
public static void setImage(ImageView imageview,String imageUrl){
Picasso.get().load(imageUrl).into(imageview);
}
}
step5.修改MainActivity。
package com.gaoting.imageviewbindingadapter;
import android.os.Bundle;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.databinding.DataBindingUtil;
import com.gaoting.imageviewbindingadapter.databinding.ActivityMainBinding;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this,R.layout.activity_main);
String imageUrl = "https://gd-hbimg.huaban.com/5688b1ee9db26fde1819506c07dbacf8dda05f488ecbe-J3hfQ8_fw658";
activityMainBinding.setImageUrl(imageUrl);
}
}
step6.在AndroidMainifest.xml中添加网络权限。
添加一行:<uses-permission android:name="android.permission.INTERNET"/>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.ImageViewBindingAdapter"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>