Android DataBinding 项目使用介绍(二)
上一节我们介绍了databinding基本用法,今天抽空写下一些实际项目开发用到的.比如listview,include标签,imageView绑定URL数据,等.
listview
在listview中我们经常使用viewHolder来实现复用view,减少内存耗用,但是数据多的时候我们使用过多的setText,很麻烦,在databinding中变得很简单,一两句代码的事,先看下,adapter中item中的xml代码.
adapter_item.xml
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
>
<data>
<import type="interest.yiyongbao.mvp.model.BillInfo"/>
<variable type="BillInfo" name="unReplayBill"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/background"
android:gravity="center_vertical"
android:orientation="vertical">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/bill_add_time"
android:textColor="@color/text_default_hint"
android:textSize="@dimen/auto_28px"/>
<TextView
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/auto_10px"
android:text="@{unReplayBill.getAdd_time}"
android:textColor="@color/text_default_hint"
android:textSize="@dimen/auto_28px"
/>
</LinearLayout>
</LinearLayout>
</layout>
在最外层布局根节点加入data标签,表示数据区,在data中导入我们需要使用的类BillInfo.
下面对adapter进行一个小封装:
public abstract class AdapterBindingImlp<T> extends BaseAdapter{
public List<T> mList;
private Context mContext;
public AdapterBindingImlp(Context context, List<T> list ) {
mList=list;
mContext=context;
}
@Override
public int getCount() {
return mList.size();
}
@Override
public Object getItem(int position) {
return mList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewDataBinding binding=null;
if(convertView==null){
int layoutId=getItemLayout();
binding= DataBindingUtil.inflate(LayoutInflater.from(mContext), layoutId,parent,false);
convertView=binding.getRoot();
convertView.setTag(binding);
AutoUtils.autoSize(convertView);
}else {
binding = (ViewDataBinding) convertView.getTag();
}
initView(binding,position);
return convertView;
}
public abstract int getItemLayout();
public abstract void initView(ViewDataBinding binding, int position);
}
- convertView是显示在UI上item的root view,在这里看出没有使用viewholder去生成view,因为viewdatabinding本身就是一个由adapter_item.xml演变的view对象,(不过注意这里adapter_item.xml,在databingding中已经进行了一个预处理,自动生成AdapterItemBinding类,而viewdatabinding正是它父类,如果需要去获取布局中的view,只需要对它进行转换即可((AdapterItembinding)viewdatabinding).time即可获取xml中id为time的控件)
- 在getview中判断convertView是否为空,为空则对该item进行初始化,写法跟我们以前基本一样,convertView=binding.getRoot()获取viewDataBinding最外层的跟布局,也就是我们通常的viewholder对应的布局view
- 最后setTag绑定这个viewdatabinding
看下Baseadapter实现类
public class URepayBillAdapter extends AdapterBindingImlp<BillInfo> {
public URepayBillAdapter(Context context, List<BillInfo> list) {
super(context, list);
}
@Override
public int getItemLayout() {
return R.layout.item_adapter_urepaybill;
}
@Override
public void initView(ViewDataBinding binding, int position) {
binding.setVariable(BR.unReplayBill,mList.get(position));
}
}
- URepayBillAdapter中只需要一句setVaeiable就可以对数据进行绑定
- 参数一的BR类是在一个类似R类,里面存放的是在xml中导入使用类的命名演变的标识,当数据进行绑定或者改变时,都是通过BR中这些标识去通知更新.
- 参数二,也就是我们所说的数据
include标签
在xml中使用include标签的时候,我们需要绑定include布局中的数据怎办?
先看下activity布局文件:activity_main.xml
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
>
<data>
<import type="interest.yiyongbao.mvp.model.UserInfo"/>
<variable type="UserInfo" name="titleInfo"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/background"
android:orientation="vertical">
<include
android:id="@+id/titleLayout"
app:UserInfo="@{titleInfo}"
layout="@layout/title_layout"/>
</LinearLayout>
</layout>
- activity_main.xml中包含着子布局title_lyout.xml,由于子布局是另一个xml,如何才能去共享主布局的数据?其实很简单,只需要把activity_main.xml中的数据按照databinding方式进行传递到include中,在include总必须保证有这个对象的定义.
- 添加命名空间xmlns:app=”http://schemas.android.com/apk/res-auto” 这个命名是我们随意的
- app:UserInfo=”@{titleInfo}”传入需要的数据titleInfo
include布局title_Layout:
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
>
<data>
<import type="interest.yiyongbao.mvp.model.UserInfo"/>
<variable type="UserInfo" name="titleInfo"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<RelativeLayout
android:id="@+id/titleLayout"
android:layout_width="match_parent"
android:layout_height="@dimen/titleLayout_110px"
android:background="@color/title_bg">
<TextView
android:id="@+id/title_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{titleInfo.name}"
android:textColor="@color/white"
android:layout_centerInParent="true"
android:textSize="@dimen/auto_35px"/>
</LineatLayout>
</layout>
- title_layout.xml中也需要有传递对象的绑定
这里要拓展一个内容,关于如何java代码中动态获取这个include中控件呢?
我们看下acitivty代码:
@Override
public void onCreate(Bundle arg0) {
super.onCreate(arg0);
ActivityMainBinding mBinding= DataBindingUtil.setContentView(this, R.layout.activity_main);
TitleLayoutBinding titleLayoutBinding=mBinding.titleLayout;
titleLayoutBinding.titleTv.setText("title");
}
可以看出通过给include设置id—->titleLayout,在include只要使用了databinding标签,也会生成一个TitleLayoutBinding,所以只要通过id,就可以直接获取这个TitleLayoutBinding.
ImageView绑定图片Url
imageview可以在xml中设置图片的url?yes
xml:
<?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>
<import type="interest.yiyongbao.mvp.model.UserInfo"/>
<variable type="UserInfo" name="titleInfo"/>
</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=""
android:layout_gravity="center_horizontal"
android:padding="10dp"
android:textSize="@dimen/auto_30px"
android:textColor="@color/text_default"
android:id="@+id/title_tv" />
<ImageView
android:layout_width="match_parent"
android:layout_height="300px"
android:src="@drawable/loading_pic2"
app:url="@{titleInfo.image}"
android:layout_gravity="center_horizontal"
android:scaleType="centerCrop"
android:id="@+id/imageView" />
</LinearLayout>
工具类:
/**
* Created by Administrator on 2017/2/25.
* 该工具是databinding自定义属性,会自动需要该注解设置图片,不需要调用
*/
public class BindImageUtil {
@BindingAdapter("url")
public static void setImgeViewSrc(ImageView view, int resId) {
view.setImageResource(resId);
}
@BindingAdapter("url")
public static void setImgeViewSrc(ImageView view, String url) {
Glide.with(view.getContext()).load(ParseUtil.BASE_IMG_URL+url).placeholder(view.getContext().getResources().getDrawable(R.drawable.loading_pic2)).crossFade().into(view);
}
}
这个工具类不需要我们去调用,根据databinding配置好,内部自动会调用,完成这个方法.
- 定义命名空间app,可以随意定义
- 设置imageview —> app:url=”@{titleInfo.image}” –>titleInfo.image就是我们的图片url,
- 命名控件的命名app:url必须与@BindingAdapter(“url”)一一对应,
- 编写注解url的方法,方法名可以自由定义,方法参数必须对应有该imageview,与url.
<下面介绍下一篇不错的databinding原理解析的博客databinding原理解析”