概念

与MVVM

配置

android {    ...    dataBinding{        enabled = true    }}

UI绑定

<?xml version="1.0" encoding="utf-8"?><layout>    <data>        <variable            name="title"            type="String" />    </data>    <androidx.constraintlayout.widget.ConstraintLayout 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"        android:layout_width="match_parent"        android:layout_height="match_parent"        tools:context=".MainActivity">        <TextView            android:id="@+id/tv1"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="@{title}"            app:layout_constraintBottom_toBottomOf="parent"            app:layout_constraintLeft_toLeftOf="parent"            app:layout_constraintRight_toRightOf="parent"            app:layout_constraintTop_toTopOf="parent" />    </androidx.constraintlayout.widget.ConstraintLayout></layout>
ActivityMainBinding binding = DataBindingUtil.setContentView(MainActivity.this,R.layout.activity_main);binding.setTitle("avcd");

事件绑定

@Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        ActivityMainBinding binding = DataBindingUtil.setContentView(MainActivity.this,R.layout.activity_main);        binding.setPresenter(new Presenter());    }    public class Presenter{        public void onClick(){            Toast.makeText(MainActivity.this,"click",Toast.LENGTH_SHORT).show();        }    }
<Button            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:onClick="@{()-> presenter.onClick()}"            />

数据绑定原理

编译 - 处理layout文件 - 解析表达式 - java编译 - 解析依赖

运算符

include

viewstub

观察者模式

public class UserInfo extends BaseObservable {    private String name;    private String password;    private Integer age;    public void setName(String name) {        this.name = name;        notifyChange();    }    public void setPassword(String password) {        this.password = password;        notifyChange();    }    public void setAge(Integer age) {        this.age = age;        notifyChange();    }}private UserInfo userInfo = new UserInfo();    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        ActivityMainBinding binding = DataBindingUtil.setContentView(MainActivity.this,R.layout.activity_main);        binding.setPresenter(new Presenter());        binding.setUser(userInfo);    }    public class Presenter implements TextWatcher {        @Override        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {        }        @Override        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {            userInfo.setName(charSequence.toString());        }        @Override        public void afterTextChanged(Editable editable) {        }    }
<layout>    <data>        <variable            name="user"            type="wang.ismy.databinding.UserInfo" />        <variable            name="presenter"            type="wang.ismy.databinding.MainActivity.Presenter" />    </data>    <LinearLayout 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"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:orientation="vertical"        tools:context=".MainActivity">        <EditText            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:onTextChanged="@{presenter::onTextChanged}"            />        <TextView            android:id="@+id/tv1"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="@{user.name}"            app:layout_constraintBottom_toBottomOf="parent"            app:layout_constraintLeft_toLeftOf="parent"            app:layout_constraintRight_toRightOf="parent"            app:layout_constraintTop_toTopOf="parent" />    </LinearLayout></layout>

高级绑定

列表绑定

public class UserAdapter extends RecyclerView.Adapter<BindingViewHolder> {    private final LayoutInflater layoutInflater;    private List<UserInfo> userInfoList = new ArrayList<>();    public UserAdapter(Context context) {        layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);    }    @Override    public int getItemViewType(int position) {        return super.getItemViewType(position);    }    @NonNull    @Override    public BindingViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {        ViewDataBinding binding =                DataBindingUtil.inflate(layoutInflater,R.layout.item_user,parent,false);        return new BindingViewHolder(binding);    }    @Override    public void onBindViewHolder(@NonNull BindingViewHolder holder, int position) {        final UserInfo userInfo = userInfoList.get(position);        holder.getBinding().setVariable(wang.ismy.databinding.BR.item,userInfo);        holder.getBinding().executePendingBindings();    }    @Override    public int getItemCount() {        return userInfoList.size();    }    public void addAll(List<UserInfo> list){        userInfoList.addAll(list);    }    public void add(UserInfo userInfo){        userInfoList.add(userInfo);        notifyItemInserted(userInfoList.size());    }    public void remove(){        if (userInfoList.size() == 0) return;        userInfoList.remove(0);        notifyItemRemoved(0);    }}
public class BindingViewHolder<T extends ViewDataBinding> extends RecyclerView.ViewHolder {    private T binding;    public BindingViewHolder(@NonNull T itemView) {        super(itemView.getRoot());        binding = itemView;    }    public T getBinding() {        return binding;    }}
binding = DataBindingUtil.setContentView(MainActivity.this,R.layout.activity_main);        binding.recyclerView.setLayoutManager(new LinearLayoutManager(this));        userAdapter = new UserAdapter(getApplicationContext());        binding.setPresenter(new Presenter());        binding.recyclerView.setAdapter(userAdapter);        userAdapter.addAll(Arrays.asList(new UserInfo("1"),                new UserInfo("2"),new UserInfo("3"),                new UserInfo("4")));

自定义属性

@BindingAdapter({"app:imageUrl","app:placeholder"})    public static void loadImage(ImageView view,                                 String url, Drawable drawable                                 ){        Glide.with(view.getContext())                .load(url)                .placeholder(drawable)                .into(view);    }binding.setUrl(url);
<layout>        <data>        <variable            name="url"            type="String" />    </data>    <LinearLayout 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"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:orientation="vertical"        tools:context=".MainActivity">        <ImageView            android:layout_width="150dp"            android:layout_height="150dp"            app:imageUrl="@{url}"            app:placeholder="@{@drawable/ic_launcher_foreground}"            />    </LinearLayout></layout>

双向绑定

        <EditText            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:text="@={model.username}"            />        <EditText            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:text="@={model.password}"            />        <Button            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:text="@{model.toString()}"            />

表达式链

<data>        <import type="android.view.View" /></data><EditText            android:id="@+id/username"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:text="@={model.username}"            android:visibility="@{model.username.length() != 5 ?View.VISIBLE:View.GONE}"            />        <EditText            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:text="@={model.password}"            android:visibility="@{username.visibility}"            />        <Button            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:text="@{model.toString()}"            android:visibility="@{username.visibility}"            />

隐式更新

        <CheckBox            android:id="@+id/checkbox"            android:layout_width="match_parent"            android:layout_height="wrap_content" />        <EditText            android:id="@+id/username"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:text="@={model.username}"            android:visibility="@{checkbox.checked ?View.VISIBLE:View.GONE}"            />

Lambda表达式

<Button            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:text="@{model.toString()}"            android:visibility="@{username.visibility}"            android:onClick="@{()->presenter.click()}"            />

动画

        binding.addOnRebindCallback(new OnRebindCallback() {            @Override            public boolean onPreBind(ViewDataBinding binding) {                ViewGroup viewGroup = (ViewGroup) binding.getRoot();                TransitionManager.beginDelayedTransition(viewGroup);                return true;            }        });