在低版本的AndroidStudio中使用DataBinding稍微有点麻烦,这里不做介绍。我这里以AndroidStuido2.1为例来介绍DataBinding。本文主要包含以下几方面内容:
1.基本使用
2.绑定ImageView
3.绑定ListView
4.点击事件处理
5.数据更新处理
好了,那就开始吧!
创建好一个Android Project之后,在gradle文件中添加如下几行代码,表示开启databinding:
android {
...
...
...
dataBinding{
enabled true
}
}
要使用数据绑定,我们得首先创建一个实体类,比如User实体类,如下:
/**
* Created by 王松 on 2016/7/31.
*/
public class UserEntity {
private String username;
private String nickname;
private int age;
public UserEntity() {
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public UserEntity(int age, String nickname, String username) {
this.age = age;
this.nickname = nickname;
this.username = username;
}
}
看完data节点我们再来看看布局文件,TextView的text属性被我直接设置为了@{user.username},这样,该TextView一会直接将UserEntity实体类的username属性的值显示出来,对于显示age的TextView,我用了String.valueOf来显示,因为大家知道TextView并不能直接显示int型数据,所以需要一个简单的转换,事实上,我们还可以在{}里边进行一些简单的运算,这些我一会再说。
最后,我们来看看Activity中该怎么写,setContentView方法不能够再像以前那样来写了,换成下面的方式:
DataBindingUtil.setContentView(this, R.layout.activity_main)
ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
UserEntity user = new UserEntity();
user.setAge(34);
user.setUsername("zhangsan");
user.setNickname("张三");
activityMainBinding.setUser(user);
}
运行,显示效果如下:
OK,那我们刚才还说到可以在@{}进行简单的计算,都有哪些计算呢?我们来看看:
我在这里给TextView设置背景的时候,做了一个简单的判断,如果用户的年龄小于30,背景就显示为蓝色,否则背景就显示为红色,DataBinding里支持小于号但是不支持大于号,索性,大于小于号我都用转义字符来表示。
另外,DataBinding对于基本的四则运算、逻辑与、逻辑或、取反位移等都是支持的,我这里不再举例。
OK,上文只是一个简单的绑定文本,下面我们来看看怎么样绑定图片,这里我们还得介绍DataBinding的另一项新功能,就是关于DataBinding自定义属性的问题,事实上,在我们使用DataBinding的时候,可以给一个控件自定义一个属性,比如我们下面即将说的这个绑定ImageView的案例。假设我现在想要通过Picasso显示一张网络图片,正常情况下这个显示很简单,可是如果我要通过DataBinding来实现,该怎么做呢?我们可以使用
@BindingAdapter
/**
* Created by 王松 on 2016/7/31.
*/
public class User {
private String username;
private String userface;
public User() {
}
public User(String userface, String username) {
this.userface = userface;
this.username = username;
}
@BindingAdapter("bind:userface")
public static void getInternetImage(ImageView iv, String userface) {
Picasso.with(iv.getContext()).load(userface).into(iv);
}
public String getUserface() {
return userface;
}
public void setUserface(String userface) {
this.userface = userface;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding dataBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
dataBinding.setUser(new User("http://img2.cache.netease.com/auto/2016/7/28/201607282215432cd8a.jpg", "张三"));
}
好了,看完了简单使用之后,不知道你有没有喜欢上DataBinding,如果还没有,那就再来看看使用DataBinding来给ListView绑定数据吧,这个你一定会喜欢上的。因为使用这中方式来绑定太简单了。
先来看看我们要做的效果吧:
就是一个ListView,左边显示图片,右边显示文本,这样一个效果。OK,那就一步一步来吧,先是主布局:
/**
* Created by 王松 on 2016/7/31.
*/
public class Food {
private String description;
private String img;
private String keywords;
private String summary;
public Food() {
}
public Food(String description, String img, String keywords, String summary) {
this.description = description;
this.img = img;
this.keywords = keywords;
this.summary = summary;
}
@BindingAdapter("bind:img")
public static void loadInternetImage(ImageView iv, String img) {
Picasso.with(iv.getContext()).load(img).into(iv);
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getImg() {
return img;
}
public void setImg(String img) {
this.img = img;
}
public String getKeywords() {
return keywords;
}
public void setKeywords(String keywords) {
this.keywords = keywords;
}
public String getSummary() {
return summary;
}
public void setSummary(String summary) {
this.summary = summary;
}
}
/**
* Created by 王松 on 2016/7/31.
*/
public class MyBaseAdapter extends BaseAdapter {
private Context context;
private LayoutInflater inflater;
private int layoutId;
private int variableId;
private List list;
public MyBaseAdapter(Context context, int layoutId, List list, int resId) {
this.context = context;
this.layoutId = layoutId;
this.list = list;
this.variableId = resId;
inflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewDataBinding dataBinding;
if (convertView == null) {
dataBinding = DataBindingUtil.inflate(inflater, layoutId, parent, false);
}else{
dataBinding = DataBindingUtil.getBinding(convertView);
}
dataBinding.setVariable(variableId, list.get(position));
return dataBinding.getRoot();
}
}
public class MainActivity extends AppCompatActivity {
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
MyBaseAdapter adapter = new MyBaseAdapter<>(MainActivity.this, R.layout.listview_item, foods, org.lenve.databinding3.BR.food);
lv.setAdapter(adapter);
}
};
private List foods;
private ListView lv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv = ((ListView) findViewById(R.id.lv));
initData();
}
private void initData() {
OkHttpClient client = new OkHttpClient.Builder().build();
Request request = new Request.Builder().url("http://www.tngou.net/api/food/list?id=1").build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
parseJson(response.body().string());
}
}
});
}
private void parseJson(String jsonStr) {
foods = new ArrayList<>();
try {
JSONObject jo = new JSONObject(jsonStr);
JSONArray tngou = jo.getJSONArray("tngou");
for (int i = 0; i < tngou.length(); i++) {
JSONObject item = tngou.getJSONObject(i);
String description = item.getString("description");
String img = "http://tnfs.tngou.net/image"+item.getString("img");
String keywords = "【关键词】 "+item.getString("keywords");
String summary = item.getString("summary");
foods.add(new Food(description, img, keywords, summary));
}
mHandler.sendEmptyMessage(0);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
至此,我们使用DataBinding的方式来给ListView加载数据就算完成了。so easy~~~
如果你使用DataBinding,我们的点击事件也会有新的处理方式,首先以ListView为例来说说如何绑定点击事件,在listview_item布局文件中每一个item的根节点添加如下代码:
....
....
....
....
....
public void onItemClick(View view) {
Toast.makeText(view.getContext(), getDescription(), Toast.LENGTH_SHORT).show();
}
单纯的更新Food对象并不能改变ListView的UI显示效果,那该怎么做呢?Google给我们提供了三种解决方案,分别如下:
让实体类继承自BaseObservable,然后给需要改变的字段的get方法添加上@Bindable注解,然后给需要改变的字段的set方法加上notifyPropertyChanged(org.lenve.databinding3.BR.description);一句即可,比如我想点击item的时候把description字段的数据全部改为111,我可以修改Food类变为下面的样子:
public class Food extends BaseObservable {
private String description;
private String img;
private String keywords;
private String summary;
public Food() {
}
public Food(String description, String img, String keywords, String summary) {
this.description = description;
this.img = img;
this.keywords = keywords;
this.summary = summary;
}
@BindingAdapter("bind:img")
public static void loadInternetImage(ImageView iv, String img) {
Picasso.with(iv.getContext()).load(img).into(iv);
}
public void onItemClick(View view) {
// Toast.makeText(view.getContext(), getDescription(), Toast.LENGTH_SHORT).show();
setDescription("111");
}
public void clickKeywords(View view) {
Toast.makeText(view.getContext(), getKeywords(), Toast.LENGTH_SHORT).show();
}
@Bindable
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
notifyPropertyChanged(org.lenve.databinding3.BR.description);
}
public String getImg() {
return img;
}
public void setImg(String img) {
this.img = img;
}
public String getKeywords() {
return keywords;
}
public void setKeywords(String keywords) {
this.keywords = keywords;
}
public String getSummary() {
return summary;
}
public void setSummary(String summary) {
this.summary = summary;
}
}
OK,这是第一种解决方案,也是比较简单常用的一种。
这种方式使用起来略微麻烦,除了继承BaseObservable之外,创建属性的方式也变成下面这种:
private final ObservableField description = new ObservableField<>();
description.get()
this.description.set(description);
/**
* Created by 王松 on 2016/7/31.
*/
public class Food extends BaseObservable {
private final ObservableField description = new ObservableField<>();
private final ObservableField img = new ObservableField<>();
private final ObservableField keywords = new ObservableField<>();
private final ObservableField summary = new ObservableField<>();
public Food() {
}
public Food(String description, String img, String keywords, String summary) {
this.description.set(description);
this.keywords.set(keywords);
this.img.set(img);
this.summary.set(summary);
}
@BindingAdapter("bind:img")
public static void loadInternetImage(ImageView iv, String img) {
Picasso.with(iv.getContext()).load(img).into(iv);
}
public void onItemClick(View view) {
// Toast.makeText(view.getContext(), getDescription(), Toast.LENGTH_SHORT).show();
setDescription("111");
}
public void clickKeywords(View view) {
Toast.makeText(view.getContext(), getKeywords(), Toast.LENGTH_SHORT).show();
}
@Bindable
public String getDescription() {
return description.get();
}
public void setDescription(String description) {
this.description.set(description);
notifyPropertyChanged(org.lenve.databinding3.BR.description);
}
public String getImg() {
return img.get();
}
public void setImg(String img) {
this.img.set(img);
}
public String getKeywords() {
return keywords.get();
}
public void setKeywords(String keywords) {
this.keywords.set(keywords);
}
public String getSummary() {
return summary.get();
}
public void setSummary(String summary) {
this.summary.set(summary);
}
}
DataBinding中给我们提供了一些现成的集合,用来存储数据,比如ObservableArrayList,ObservableArrayMap,因为这些用的少,我这里就不做介绍了。
本文共涉及到三个Demo,由于CSDN对上传文件大小的限制,我分三次上传,下载地址如下:
1.http://download.csdn.net/detail/u012702547/9591142
2.http://download.csdn.net/detail/u012702547/9591150
3.http://download.csdn.net/detail/u012702547/9591160
以上。