一、DataBinding
1.1 在Module的build.gradle android模块中添加如下配置
代码地址 https://github.com/MichealPan9999/DataBinding-MVVM
android {
dataBinding {
enabled = true
}
}
1.2 创建一个简单的JavaBean对象
public class UserBean {
private String name; //姓名
private int age; //年龄
public UserBean(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
1.3 使用了DataBinding之后的Activity的布局文件activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="user"
type="com.zx.databindingdemo.bean.UserBean" />
</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="@{user.name}" />
<!--注意:这里age是int类型,必须转化为String,否则会运行时异常-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{String.valueOf(user.age)}" />
</LinearLayout>
</layout>
1.4 MainActivity
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
UserBean userBean = new UserBean ("张三", "25");
binding.setUser(userBean );
}
}
但是如果你在实际编写代码的过程中,你会发现并没有执行编译、运行之类等操作,ActivityMainBinding这个类就直接能用了,竟然还有这种操作?其实是Android Studio 这个IDE自动帮我们做了这一步,在默认情况下,系统会使用Android Studio为我们自动生成databinding相关的代码,但是这种方式生成的代码不能调试,如果你想通过点击ActivityMainBinding跳转到它的源码中,你会发现并不能如你所愿,而是会跳转到对应的布局文件中。那么如果我们确实要查看ActivityMainBinding的源码并且还想调试,我们就需要通过另外一种方式:手动编译代码。这两种方式可以通过Android Studio的设置面板修改。
1.5 引入一些高级变量variable
1.5.1 import导包及xml中添加运算
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="java.util.List" />
<import type="java.util.Map" />
<import type="com.example.panzq.mvvm.bean.UserBean" />
<import type="android.view.View" />
<!--泛型的支持会在编译时期报红线,但是是可以直接运行的
但是需要通过转义字符才行,如:<号用<表示;>号用>表示;-->
<variable
name="list"
type="List<String>" />
<variable
name="map"
type="Map<String,Object>" />
<variable
name="array"
type="String[]" />
<variable
name="muser"
type="UserBean" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{list[0]}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{list.get(1)}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="@{map[`key0`]}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{map.get(`key1`)}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="@{array[0]}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{array[1]}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{muser.name}"
android:visibility="@{((muser.age > 18) ? View.GONE:View.VISIBLE)}" />
</LinearLayout>
</layout>
ActivityMain2Binding binding = DataBindingUtil.setContentView(this, R.layout.activity_main2);
List<String> list = new ArrayList<>();
list.add("List1");
list.add("List2");
binding.setList(list);
HashMap<String, Object> map = new HashMap<>();
map.put("key0", "map_value0");
map.put("key1", "map_value1");
binding.setMap(map);
String[] array = {"字符串1", "字符串2"};
binding.setArray(array);
UserBean userBean = new UserBean("张三",18);
binding.setMuser(userBean);
list和map这里我没有用List<String>和Map<String,Object>,而是用的List<String>和Map<String,Object>原因是在data中,有些字符是必须用转义字符才能编译通过,上面把<>换成转义字符的写法虽然会在编译时是红色的,但是不用担心,会编译通过的,下面给出常用的转义字符。
附:常用的转义字符
| 显示结果 | 描述 | 转义字符 | 十进制 |
|---|---|---|---|
| 空格 |  ; |  ; | |
| < | 小于号 | <; | <; |
| > | 大于号 | >; | >; |
| & | 与号 | &; | &; |
| " | 引号 | "; | "; |
| ‘ | 撇号 | &apos; | '; |
| × | 乘号 | ×; | ×; |
| ÷ | 除号 | ÷; | ÷; |
1.5.2 别名
如果我们import了两个不同路径,但名称相同的类,可以借助于别名来解决,别名借助alias字段来标识。
<import type="com.example.panzq.mvvm.bean.UserBean" />
<import type="com.example.panzq.mvvm.bean.UserBean" alias="UserBean2"/>
...
<variable
name="muser"
type="UserBean" />
<variable
name="muser2"
type="UserBean2" />
...
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{muser.name}"
android:visibility="@{((muser.age > 18) ? View.GONE:View.VISIBLE)}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{muser2.name}"
android:visibility="@{((muser2.age > 18) ? View.GONE:View.VISIBLE)}" />
UserBean userBean = new UserBean("张三",18);
binding.setMuser(userBean);
UserBean userBean2 = new UserBean("李四",17);
binding.setMuser2(userBean2);
1.5.3 android:onClick事件处理
下面给出几种实现方式:
- 布局中引入OnClickListener的变量
- 方法调用
<variable
name="clickListener"
type="android.view.View.OnClickListener" />
...
<Button
android:id="@+id/click_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{clickListener}"
android:text="button" />
binding.setClickListener(this);
...
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.click_btn:
Toast.makeText(Main2Activity.this, "点击了按钮", Toast.LENGTH_SHORT).show();
break;
}
}
二 DataBinding & RecyclerView
2.1 处理找不到符号 RecyclerView问题
import android.support.v7.widget.RecyclerView;时提示找不到符号RecyclerView
2.1.1 配置aar方法
1. 找到sdk目录下的recyclerview-v7-****.aar文件,如:
D:\Program Files\androidstudio3\sdk2\extras\android\m2repository\com\android\support\recyclerview-v7\24.0.0\recyclerview-v7-24.0.0.aar
2. 将aar文件拷贝到项目的libs目录下build.gradle中加载aar文件
apply plugin: 'com.android.application'android { compileSdkVersion 28 dataBinding { enabled = true } defaultConfig { applicationId "com.example.recyclerview" minSdkVersion 22 targetSdkVersion 28 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } }}repositories { flatDir { dirs 'libs' }}dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:28.+' implementation 'com.android.support.constraint:constraint-layout:1.0.2' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.1' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' compile(name: 'recyclerview-v7-24.0.0', ext: 'aar')}
执行完Sync Now以后便可以正常导包
import android.support.v7.widget.RecyclerView;
2.2 Adapter 配置
BaseBindRecyclerViewAdapter
public abstract class BaseBindRecyclerViewAdapter<T> extends RecyclerView.Adapter {
public List<T> mList; //数据源
public LayoutInflater inflater;
public BaseBindRecyclerViewAdapter(Context context, List<T> mList) {
this.mList = mList;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
return onCreateMyViewHolder(viewGroup, i);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int i) {
onBindMyViewHolder(viewHolder, i);
}
@Override
public int getItemCount() {
return mList.size();
}
//获取Item布局
public abstract RecyclerView.ViewHolder onCreateMyViewHolder(ViewGroup parent, int viewType);
//绑定数据
public abstract void onBindMyViewHolder(RecyclerView.ViewHolder holder, int position);
}
MutiItemAdapter
public class MultiItemAdapter extends BaseBindRecyclerViewAdapter<IBaseBindingAdapterItem> {
public MultiItemAdapter(Context context, List<IBaseBindingAdapterItem> mList) {
super(context, mList);
}
@Override
public int getItemViewType(int position) {
return mList.get(position).getItemViewType();
}
@Override
public RecyclerView.ViewHolder onCreateMyViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case R.layout.item_fruit:
ItemFruitBinding itemFruitBinding = DataBindingUtil.inflate(inflater, R.layout.item_fruit, parent, false);
return new FruitViewHolder(itemFruitBinding);
case R.layout.item_text:
ItemTextBinding itemTextBinding = DataBindingUtil.inflate(inflater, R.layout.item_text, parent, false);
return new TextViewHolder(itemTextBinding);
default:
ItemFruitBinding binding = DataBindingUtil.inflate(inflater, R.layout.item_fruit, parent, false);
return new FruitViewHolder(binding);
}
}
@Override
public void onBindMyViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof FruitViewHolder) {
FruitItem fruitBean = (FruitItem) mList.get(position);
((FruitViewHolder) holder).getBinding().setItem(fruitBean);
((FruitViewHolder) holder).getBinding().executePendingBindings(); //解决databinding闪烁问题
} else if (holder instanceof TextViewHolder) {
TextItem textBean = (TextItem) mList.get(position);
((TextViewHolder) holder).getBinding().setItem(textBean);
((TextViewHolder) holder).getBinding().executePendingBindings(); //解决databinding闪烁问题
}
}
}
但是用了DataBinding以后,主要有3个地方发生了变化,ViewHolder, onCreateViewHolder,onBindMyViewHolder。
2.2.1 编写ViewHolder
这里我的RecyclerView有两种布局,并且布局全部是用databinding编写的
class FruitViewHolder extends RecyclerView.ViewHolder {
private ItemFruitBinding binding;
public ItemFruitBinding getBinding() {
return binding;
}
public FruitViewHolder(ItemFruitBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
}
...
class TextViewHolder extends RecyclerView.ViewHolder {
private ItemTextBinding binding;
public ItemTextBinding getBinding() {
return binding;
}
public TextViewHolder(ItemTextBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
}
2.2.2 重写onCreateViewHodler(ViewGroup parent,int viewType)
@Override
public RecyclerView.ViewHolder onCreateMyViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case R.layout.item_fruit:
ItemFruitBinding itemFruitBinding = DataBindingUtil.inflate(inflater, R.layout.item_fruit, parent, false);
return new FruitViewHolder(itemFruitBinding);
case R.layout.item_text:
ItemTextBinding itemTextBinding = DataBindingUtil.inflate(inflater, R.layout.item_text, parent, false);
return new TextViewHolder(itemTextBinding);
default:
ItemFruitBinding binding = DataBindingUtil.inflate(inflater, R.layout.item_fruit, parent, false);
return new FruitViewHolder(binding);
}
}
2.2.3.onBindViewHolder(RecyclerView.ViewHolder holder,int position)方法
@Override
public void onBindMyViewHolder(RecyclerView.ViewHolder holder, int position) {//绑定数据
if (holder instanceof FruitViewHolder) {
FruitItem fruitBean = (FruitItem) mList.get(position);
((FruitViewHolder) holder).getBinding().setItem(fruitBean);
((FruitViewHolder) holder).getBinding().executePendingBindings(); //解决databinding闪烁问题
} else if (holder instanceof TextViewHolder) {
TextItem textBean = (TextItem) mList.get(position);
((TextViewHolder) holder).getBinding().setItem(textBean);
((TextViewHolder) holder).getBinding().executePendingBindings(); //解决databinding闪烁问题
}
}
2.3 MainAcitivity 填充数据
public class MainActivity extends AppCompatActivity {
private MultiItemAdapter multiItemAdapter;
private List<IBaseBindingAdapterItem> mList = new ArrayList<>(); //数据源
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
ActivityMainBinding binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
initData();
multiItemAdapter = new MultiItemAdapter(this,mList);//获取填充的数据
LinearLayoutManager layoutManager = new LinearLayoutManager(this, OrientationHelper.VERTICAL,false);
binding.recyclerView.setLayoutManager(layoutManager);
binding.recyclerView.setAdapter(multiItemAdapter);//填充数据到R.id.recyclerView
}
private void initData() {
mList.add(new TextItem("标题1"));
mList.add(new FruitItem(R.mipmap.fruit, "苹果"));
mList.add(new FruitItem(R.mipmap.fruit, "香蕉"));
mList.add(new TextItem("标题2"));
mList.add(new TextItem("标题3"));
mList.add(new FruitItem(R.mipmap.fruit, "桃子"));
mList.add(new TextItem("标题4"));
mList.add(new FruitItem(R.mipmap.fruit, "梨"));
mList.add(new TextItem("标题5"));
}
}
来源:https://www.cnblogs.com/qiangge-python/p/9715138.html