BindView的使用-XML的控件绑定

使用BindView有这样一个特点,即编写好的xml布局文件需要build一下,生成其对应的binding类才能被activity或自定义布局使用,即:activity_main.xml文件编译后生成的类为:ActivityMainBinding.java。
在本人使用的这些日子当中,发现其实BindView这个东西确实没有Butterknife好用!每次编写好的xml需要编译不说,而且经常在使用其编译好的控件时报红!
不过如果你会Kotlin的话,你就不需要学习BindView和Butterknife了,因为Kotlin的使用已经相当简洁和方便了[嗯哼~有点偏题了]

这次文章主要介绍xml文件的控件绑定

步骤

Step 1:在app module下的build.gradle中添加以下代码
android {
    compileSdkVersion 28
    defaultConfig {
        ...
    }
    buildTypes {
       ...
    }
    // 添加如下代码
    dataBinding {
        enabled = true
    }
}
Step 2:编写xml文件,需要在布局最外层添加<layout></layout>标签
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
    </data>
    <android.support.constraint.ConstraintLayout
        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/hello_world"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World!"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </android.support.constraint.ConstraintLayout>
</layout>

到目前为止,我们的基本任务就完成了,然后需要做的就是编译一下我们的项目,让其生成xml文件对应的类。这个类可以生成我们布局文件中每个组件对应的ID信息,有这个ID信息,我们就能使用这个组件了。

我们看一下生成的这个类

生成的类名根据xml文件的文件名来匹配,例如xml文件名为:activity_main.xml转换成binding类名为:ActivityMainBinding

public class ActivityMainBinding extends android.databinding.ViewDataBinding  {

    @Nullable
    private static final android.databinding.ViewDataBinding.IncludedLayouts sIncludes;
    @Nullable
    private static final android.util.SparseIntArray sViewsWithIds;
    static {
        sIncludes = null;
        sViewsWithIds = new android.util.SparseIntArray();
        sViewsWithIds.put(R.id.hello_world, 1);
    }
    // views    大家看这里!这里!里!---这个对象就是我们所说的xml里面生成的对应组件
    @NonNull
    public final android.widget.TextView helloWorld;
    @NonNull
    private final android.support.constraint.ConstraintLayout mboundView0;
    // variables
    // values
    // listeners
    // Inverse Binding Event Handlers

    public ActivityMainBinding(@NonNull android.databinding.DataBindingComponent bindingComponent, @NonNull View root) {
        super(bindingComponent, root, 0);
        final Object[] bindings = mapBindings(bindingComponent, root, 2, sIncludes, sViewsWithIds);
        this.helloWorld = (android.widget.TextView) bindings[1];
        this.mboundView0 = (android.support.constraint.ConstraintLayout) bindings[0];
        this.mboundView0.setTag(null);
        setRootTag(root);
        // listeners
        invalidateAll();
    }

    @Override
    public void invalidateAll() {
        synchronized(this) {
                mDirtyFlags = 0x1L;
        }
        requestRebind();
    }

    @Override
    public boolean hasPendingBindings() {
        synchronized(this) {
            if (mDirtyFlags != 0) {
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean setVariable(int variableId, @Nullable Object variable)  {
        boolean variableSet = true;
            return variableSet;
    }

    @Override
    protected boolean onFieldChange(int localFieldId, Object object, int fieldId) {
        switch (localFieldId) {
        }
        return false;
    }

    @Override
    protected void executeBindings() {
        long dirtyFlags = 0;
        synchronized(this) {
            dirtyFlags = mDirtyFlags;
            mDirtyFlags = 0;
        }
        // batch finished
    }
    // Listener Stub Implementations
    // callback impls
    // dirty flag
    private  long mDirtyFlags = 0xffffffffffffffffL;

    @NonNull
    public static ActivityMainBinding inflate(@NonNull android.view.LayoutInflater inflater, @Nullable android.view.ViewGroup root, boolean attachToRoot) {
        return inflate(inflater, root, attachToRoot, android.databinding.DataBindingUtil.getDefaultComponent());
    }
    @NonNull
    public static ActivityMainBinding inflate(@NonNull android.view.LayoutInflater inflater, @Nullable android.view.ViewGroup root, boolean attachToRoot, @Nullable android.databinding.DataBindingComponent bindingComponent) {
        return android.databinding.DataBindingUtil.<ActivityMainBinding>inflate(inflater, com.gudong.browser.bindviewapp.R.layout.activity_main, root, attachToRoot, bindingComponent);
    }
    @NonNull
    public static ActivityMainBinding inflate(@NonNull android.view.LayoutInflater inflater) {
        return inflate(inflater, android.databinding.DataBindingUtil.getDefaultComponent());
    }
    @NonNull
    public static ActivityMainBinding inflate(@NonNull android.view.LayoutInflater inflater, @Nullable android.databinding.DataBindingComponent bindingComponent) {
        return bind(inflater.inflate(com.gudong.browser.bindviewapp.R.layout.activity_main, null, false), bindingComponent);
    }
    @NonNull
    public static ActivityMainBinding bind(@NonNull android.view.View view) {
        return bind(view, android.databinding.DataBindingUtil.getDefaultComponent());
    }
    @NonNull
    public static ActivityMainBinding bind(@NonNull android.view.View view, @Nullable android.databinding.DataBindingComponent bindingComponent) {
        if (!"layout/activity_main_0".equals(view.getTag())) {
            throw new RuntimeException("view tag isn't correct on view:" + view.getTag());
        }
        return new ActivityMainBinding(bindingComponent, view);
    }
    /* flag mapping
        flag 0 (0x1L): null
    flag mapping end*/
    //end
}
Step 3: 好了,接下来我们介绍一下如何调用生成的这个类文件

我们先创建一个基类,该基类用于我们对大多数要使用BindView的activity有通用作用。

public abstract class BaseBindActivity<VB extends ViewDataBinding> extends AppCompatActivity {
    protected VB mBinding;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 获取视图
        View view = getLayoutInflater().inflate(getLayoutResId(), null, false);
        // databinding绑定视图
        mBinding = DataBindingUtil.bind(view);
        setContentView(view);
    }

    /**
     * get layout resource id;
     * @return
     */
    @LayoutRes
    protected abstract int getLayoutResId();
}
Step 4:在MainActivity.java类中继承该基类
public class MainActivity extends BaseBindActivity<ActivityMainBinding> {
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        TextView helloworld = mBinding.helloWorld;
        helloworld.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity.this,"hello world",Toast.LENGTH_SHORT).show();
            }
        });
    }

    @Override
    protected int getLayoutResId() {
        return R.layout.activity_main;
    }
}

如此,我们任务就大功告成了。

后面抽时间来介绍一下数据的绑定。