android中databinding的使用

    之前比較熟練使用MVP的框架,由於前段時間幫前端寫了段時間的vue,發現雙向綁定真的用的很方便,早就聽說MVVM也是雙向綁定的,用着很方便,再也不需要編寫findViewById,其實就是一個數據綁定框架,我就我現在的狀態也是一邊學一邊寫,從0到框架的使用,也算做個記錄吧

Ⅰ.DataBinding的準備工作

Ⅱ.DataBinding中實現對象,List和Map集合,數組等綁定和字段綁定

Ⅲ.使用DataBinding實現RecyclerView的綁定

Ⅳ.數據的更新操作

 

Ⅰ.以下是DataBinding的準備工作

1.在app的build.gradle的android模塊中添加

android {
    dataBinding {
        enabled = true
    }
}

2.在project的build.gradle中的allprojects標籤下添加mavenCentral()

allprojects {
    repositories {
        mavenCentral()
    }
}

 

3.以往我們在寫佈局的時候會直接引用android佈局裏面的LinearLayout或者RelativeLayout等,但是我們使用binding的時候需要在根節點添加小寫的layout類似下圖

 

注意:binding類是根據xml佈局文件的名字生成的,最後別忘記了Sync Now
activity_main.xml->ActivityMainBinding
activity_item.xml->ActivityItemBinding
splash_test.xml->SplashTestBinding
依此類推

 

Ⅱ.現在開始第二步 DataBinding中實現對象,List和Map集合,數組等綁定和字段綁定

1.我們首先可以創建一個對象Student

public class Student {

    private int grade;  //年級
    private int age;    //年齡
    private String name;//名字
    private int score;  //分數

    public int getGrade() {
        return grade;
    }

    public void setGrade(int grade) {
        this.grade = grade;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }
}

2.我們創建一個普通佈局(注意,如果字段爲int字段需要轉爲String

<?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="student"
            type="com.huaweidun.gpuimageapp.Student" />
    </data>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".StudentActivity">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{student.name}"
            />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{String.valueOf(student.age)}"
            />
    </LinearLayout>
</layout>

那麼問題來了,如果我想讓這兩個字段拼接在一起要怎麼做呢,直接相加,我們這裏還支持表達式,三元表達式,是不是很方便呢

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text='@{"哦豁"+student.name+student.age}'
            android:visibility="@{age>10?View.VISIBLE:View.GONE}"
            />

如果還有別的字段,我們可以在String.xml內拼接,等等還有很多其他格式化和替換拼接的,可自行百度

<resources>
    <string name="app_name">TestApp</string>
    <string name="custom_str">我的名字叫:%s,我年齡:%s</string>
</resources>
 <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text='@{@string/custom_str(student.name,student.age)}'
            />

運行效果

 

引入複雜變量,例如Map,List,數組,單個字段,接下來我們就使用一下吧,這裏的&lt;是小於號&gt;是大於號,這裏是需要轉義的,要不然可能會出現編譯錯誤

<layout xmlns:android="http://schemas.android.com/apk/res/android">    
    <data>
        <import type="java.util.List"/>
        <import type="java.util.Map"/>

        <variable
            name="list"
            type="List&lt;String&gt;" />
        <variable
            name="map"
            type="Map&lt;String,Object&gt;" />
        <variable
            name="array"
            type="String[]" />
    </data>

    <LinearLayout 
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{list.get(0)}"
          />
         <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{map[`key`]}"
          />

         <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{array[0]}"
          />
    </LinearLayout>
</layout>

然後我們在activity裏面進行設置這些變量,就可以顯示了

        listString.add("string1");
        listString.add("String2");
        binding.setList(listString);
        map.put("key1","key值1");
        map.put("key2","key值2");
        binding.setMap(map);
        String[] arr={"字符串1","字符串2"};
        binding.setArray(arr);

 Ⅲ.好了,binding用法的基礎用法我們基本上可以用了,我們可以呢嘗試用databinding的方法寫一個recyclerview的綁定

 <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/rv"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

首先在佈局裏面添加上recyclerview的佈局,接下來該我們去寫適配器了,其實跟我們寫界面時候是一樣的,item的佈局名字+binding進行相應引用

public class MultiItemAdapter extends RecyclerView.Adapter<MultiItemAdapter.ViewHolder> {

    private MyItemClickListener itemClickListener;
    private ItemUserListBinding binding;
    private LayoutInflater layoutInflater;
    private List<UserBean> userBeans;
    private Context mContext;
    private int variableId;

    public MultiItemAdapter(Context context, List<UserBean> list,int variableId){
        this.layoutInflater=LayoutInflater.from(context);
        this.userBeans=list;
        this.mContext=context;
        this.variableId=variableId;
    }
    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        binding= DataBindingUtil.inflate(layoutInflater,R.layout.item_user_list,parent,false);
        ViewHolder viewHolder=new ViewHolder(binding.getRoot(),itemClickListener);
        viewHolder.setBinding(binding);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        holder.getBinding().setVariable(variableId,userBeans.get(position));
        holder.getBinding().executePendingBindings();
    }

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

    public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{

        public MyItemClickListener mMyItemClickListener;
        private ViewDataBinding binding;

        public ViewHolder(@NonNull View itemView,MyItemClickListener myItemClickListener) {
            super(itemView);
            this.mMyItemClickListener=myItemClickListener;
            itemView.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            if(mMyItemClickListener!=null){
                mMyItemClickListener.onItemClick(v,getPosition());
            }
        }

        public ViewDataBinding getBinding(){
            return  binding;
        }

        public void setBinding(ViewDataBinding binding){
            this.binding=binding;

        }
    }

    public interface MyItemClickListener{
        void onItemClick(View view,int position);
    }

    public void setOnItemClicklistener(MyItemClickListener myItemClickListener){
        this.itemClickListener=myItemClickListener;
    }
}

下面是我們的佈局文件item_user_list文件

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

    <data>
        <variable
            name="user"
            type="com.huaweidun.gpuimageapp.UserBean" />
    </data>
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
            />
        <TextView
            android:id="@+id/age"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{String.valueOf(user.age)}"
            />
    </LinearLayout>
</layout>

 

 

然後在界面中去填充我們的適配器,BR不用管,相當於我們的R文件是自動生成的

private void showRecycler(){
        LinearLayoutManager linearLayoutManager=new LinearLayoutManager(this);
        linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        binding.rv.setLayoutManager(linearLayoutManager);
        //設置適配器
        MultiItemAdapter multiItemAdapter=new MultiItemAdapter(this,listUser,BR.user);
        binding.rv.setAdapter(multiItemAdapter);
        multiItemAdapter.setOnItemClicklistener(new MultiItemAdapter.MyItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {
                Toast.makeText(MainActivity.this,listUser.get(position).getUserName(),Toast.LENGTH_SHORT).show();
            }
        });
    }

 

 

Ⅳ.數據的更新操作 

之前我們的數據更新的時候都是settext等,當我們的數據發生變化的時候,需要手動設置數據源,從而使得UI界面發生改變

把我們的實體類去繼承BaseObservable,然後在get上面添加@Bindable註解,在set中添加通知更新就可以了

public class Article extends BaseObservable {

    private String content;

    public Article (String content) {
        this.content = content;
    }

    @Bindable
    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
        notifyPropertyChanged(BR.content);
    }
然後當我們的數據發生變化的時直接使用article.setContent("我發生了改變")即可

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章