Android DataBinding 你好!

版权声明:本文为博主原创文章,遵循 CC 4.0 BY 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/a_zhon/article/details/87946209

一:使用DataBinding的第一步,只需要在app/build.gradle开启它

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "azhon.com.viewbinding"
        //....
    }
    //开启dataBinding
    dataBinding {
        enabled = true
    }
}

二:将布局文件根元素修改为<layout>

<?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>

        <import />

        <variable />
    </data>

    <!-- layout 下只能有一个子节点 -->

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <!-- 布局内容 -->

    </LinearLayout>
</layout>
  • 在布局文件中我们可以通过快捷修复来将布局文件自动修改为符合databinding的布局
    在这里插入图片描述
  • 需要注意的是:layout 下只能有一个子节点

三:下面通过一些实例来介绍具体的使用

①为TextView绑定一个UserName

  • 首先需要在xml中指定variable数据,然后在TextView进行绑定,如下:
<?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="userName"
            type="String" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:gravity="center"
            android:text="@{userName,default=我是默认的值}"
            android:textColor="#333333" />
    </LinearLayout>
</layout>
  • 在Activity中对这个布局加载,然后在设置userName的值
public class FirstMainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        FirstMainBinding dataBinding = DataBindingUtil.setContentView(this, R.layout.first_main);
        //设置数据
        dataBinding.setUserName("Hello 阿钟");
    }
}

1、Activity加载布局需要使用DataBindingUtil.setContentView(),然后返回当前布局的*Binding对象,此类的命名规则为布局文件名称的驼峰命名加上Binding:如activity_main则为ActivityMainBinding
2、在布局中都是通过@{}来进行引用变量、数据等
3、如果需要对字符串进行拼接的话就需要这样子写'@{"拼接字符串"+userName}'

②当然在布局中也是可以直接使用List、Map等

<?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>
    	<!--引入数据类型-->
        <import type="java.util.List" />
        <import type="java.util.Map" />
        
        <!--与元素类型 "variable" 相关联的 "type" 属性值不能包含 '<' 字符。
        这里 < 需要被转义为 &lt;-->
        <variable
            name="list"
            type="List&lt;String>" />
        <variable
            name="map"
            type="Map&lt;String,String>" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <!--取list集合中的第一个元素-->
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{list[0]}"/>
        <!--取map集合中key = "key"元素-->
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text='@{map.get("key")}' />
    </LinearLayout>
</layout>

然后通过当前布局文件的Binding对ListMap进行赋值,如下:

public class FirstMainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        FirstMainBinding dataBinding = DataBindingUtil.setContentView(this, R.layout.first_main);
        //设置数据
        dataBinding.setList(Arrays.asList("Larry", "Moe", "Curly"));
        HashMap<String, String> map = new HashMap<>();
        map.put("key", "我是map的值");
        dataBinding.setMap(map);
    }
}

③对View进行onClick事件绑定

<?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="model"
            type="com.azhon.viewbinding.FirstMainActivity" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <!--第一种写法-->
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="@{model::click}"/>
        <!--第二种写法-->
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="@{model.click}"/>
        <!--第三种写法-->
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="@{()-> model.click2()}"/>   
        <!--第四种写法 调用有参数的函数-->
        <!--theView 指代当前的TextView-->
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="@{(thisView)-> model.click3(thisView,12)}"/>
    </LinearLayout>
</layout>

相对应的Activity代码

public class MainActivity extends AppCompatActivity {
    
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         FirstMainBinding dataBinding = DataBindingUtil.setContentView(this, R.layout.first_main);
         //对model进行赋值
         mainBinding.setModel(this);
     }
     
     public void click(View view) {
        Toast.makeText(this, "DataBinding点击事件", Toast.LENGTH_SHORT).show();
     }
     public void click2() {
         Toast.makeText(this, "DataBinding点击事件(无参数)", Toast.LENGTH_SHORT).show();
     }
     public void click3(View view, int p) { 
         Toast.makeText(this, "DataBinding点击事件,参数:" + p, Toast.LENGTH_SHORT).show();
     }
}

④在布局中进行少量的运算,所支持的运算符如下:

!=%+-*/<>==<=>=<<>>>>>

或者使用三目运算符show ? View.VISIBLE : View.GONE

<?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>
        <!--导入View类-->
        <import type="android.view.View" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{String.valueOf(index + 1)}"
            android:visibility="@{age > 13 ? View.GONE : View.VISIBLE}"
            android:transitionName='@{"image_" + id}'/>
    </LinearLayout>
</layout>

四:dataBinding结合RecyclerView进行使用

①布局文件中添加RecyclerView

<?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>

   </data>

   <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:orientation="vertical">

       <android.support.v7.widget.RecyclerView
           android:id="@+id/rv"
           android:layout_width="match_parent"
           android:layout_height="match_parent" />
   </LinearLayout>
</layout>

②创建一个实体类,用来做为RecyclerView的数据源User

public class User  {
    private String userName;
    private String userNum;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }
    
    public String getUserNum() {
        return userNum;
    }

    public void setUserNum(String userNum) {
        this.userNum = userNum;
    }
}

③编写RecyclerView的Item布局,引入User这个实体类

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
    	<!-- Item的数据源为User -->
        <variable
            name="user"
            type="com.azhon.viewbinding.User" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#eeeeee"
        android:gravity="center_vertical"
        android:orientation="vertical"
        android:paddingHorizontal="16dp"
        android:paddingVertical="8dp">

        <TextView
            android:id="@+id/tv_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text='@{"姓名:"+user.userName,default=阿钟}' />

        <TextView
            android:id="@+id/tv_num"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text='@{"序号:"+user.userNum,default=123456}' />
    </LinearLayout>
</layout>

④结合DataBinding创建RecycleerView适配器

public class TestAdapter extends RecyclerView.Adapter<TestAdapter.MyViewHolder> {

    private List<User> users;
    private Context context;

    public TestAdapter(List<User> users, Context context) {
        this.users = users;
        this.context = context;
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int i) {
        LayoutInflater inflater = LayoutInflater.from(context);
        ItemRvBinding binding = DataBindingUtil.inflate(inflater, R.layout.item_rv, parent, false);
        return new MyViewHolder(binding.getRoot());
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int i) {
        ItemRvBinding binding = DataBindingUtil.getBinding(holder.itemView);
        binding.setUser(users.get(i));
        //迫使数据立即绑定
        binding.executePendingBindings();
    }

    @Override
    public int getItemCount() {
        return users.size();
    }

    public class MyViewHolder extends RecyclerView.ViewHolder {
        public MyViewHolder(View itemView) {
            super(itemView);
        }
    }

}
  • 通过DataBindingUtil.inflate()加载Item的布局,返回Item的*Binding对象
  • onBindViewHolder中设置Item的数据binding.setUser(users.get(i));需要调用binding.executePendingBindings();对数据进行立即绑定,防止数据错乱

⑤接下来就简单了,为Adapter设置数据即可

FirstMainBinding dataBinding = DataBindingUtil.setContentView(this, R.layout.first_main);
//通过dataBinding找到布局View
RecyclerView recyclerView = dataBinding.rv;
recyclerView.setLayoutManager(new LinearLayoutManager(this));
List<User> users = new ArrayList<>();
for (int i = 0; i < 30; i++) {
    User user = new User();
    user.setUserName("用户 " + i);
    user.setUserNum(String.valueOf(Math.round(Math.random()) * 100000));
    users.add(user);
}
TestAdapter adapter = new TestAdapter(users, this);
recyclerView.setAdapter(adapter);

好了基本的一些DataBinding使用到这里就说完了,感兴趣的大伙可以自己动手实践一下

展开阅读全文

没有更多推荐了,返回首页