在上篇Android databinding详解(一)–layout解析中我们学习了data binding在layout中的结构和语法,如果没看过的话,最好看一遍,两个章节是相互关联的,在本篇文章中主要讲述的是集成了data binding框架以后,我们的Activity文件中应该如何书写?下面依旧是先粘贴上Activity所有的代码, 然后通过代码讲述它与普通的Activity的不同之处。
MainActivity
package wshuttle.com.testmvvm.ui;
import android.databinding.DataBindingUtil;
import android.databinding.ObservableBoolean;
import android.databinding.ObservableInt;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
import wshuttle.com.testmvvm.BR;
import wshuttle.com.testmvvm.R;
import wshuttle.com.testmvvm.adapter.BaseListViewAdapter;
import wshuttle.com.testmvvm.adapter.BaseRecycleViewAdapter;
import wshuttle.com.testmvvm.bean.OrderInfo;
import wshuttle.com.testmvvm.bean.UserInfo;
import wshuttle.com.testmvvm.databinding.ActivityMainBinding;
/**
* MVVM:@{},@={},data import variable Event(事件返回值相同即可)
*/
public class MainActivity extends BaseActivity {
public ObservableBoolean show = new ObservableBoolean();
public ObservableInt imageUrl = new ObservableInt(R.mipmap.ic_launcher);
private OrderInfo orderInfo;
ActivityMainBinding bing;
BaseRecycleViewAdapter adapter;
ListView listView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bing = DataBindingUtil.setContentView(this, R.layout.activity_main);
Toolbar toolbar = bing.toolbar;
setSupportActionBar(toolbar);
toolbar.setTitle("ToolBar");
toolbar.setTitle("Use");
orderInfo = new OrderInfo("20160922142752", "曹操");
bing.notifyPropertyChanged(BR.imageUrl);
show.set(true);
bing.setShow(show);
bing.setUserInfo(new UserInfo());
bing.setMyEventHandler(new MyEventHandler());
bing.setOrderInfo(orderInfo);
bing.setImageUrl(imageUrl);
handler.postDelayed(new Runnable() {
@Override
public void run() {
orderInfo.setOrderid("ABCDEFGHIJK");
orderInfo.setRescueName("刘备");
// adapter.addItem(new UserInfo(6,"关羽","admin"));
show.set(false);
imageUrl.set(R.drawable.big6);
}
}, 3000);
listView = bing.listView;
// initRecyclerView();
initListView();
}
Handler handler = new Handler(){};
List<UserInfo> lists;
private void initListView() {
lists = new ArrayList<>();
UserInfo userInfo1 = new UserInfo(R.string.app_name, "admin", "admin");
UserInfo userInfo2 = new UserInfo(R.string.app_name, "张三", "user");
UserInfo userInfo3 = new UserInfo(R.string.app_name, "李四", "user");
UserInfo userInfo4 = new UserInfo(R.string.app_name, "王五", "user");
lists.add(userInfo1);
lists.add(userInfo2);
lists.add(userInfo3);
lists.add(userInfo4);
BaseListViewAdapter listAdapter = new BaseListViewAdapter(lists, R.layout.layout_user_item, BR.userInfo);
listView.setAdapter(listAdapter);
}
// private void initRecyclerView() {
// bing.recyclerView.setHasFixedSize(true); //用来使RecyclerView保持固定的大小,该信息被用于自身的优化。
// LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
// linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
// bing.recyclerView.setLayoutManager(linearLayoutManager);//设置布局管理器,决定视图放在画面的哪个位置
// bing.recyclerView.setItemAnimator(new DefaultItemAnimator());//设置Item变化的动画
//// bing.recyclerView.addItemDecoration(); //添加分割线
// lists = new ArrayList<>();
// UserInfo userInfo1 = new UserInfo(1,"admin","admin");
// UserInfo userInfo2= new UserInfo(2,"张三","user");
// UserInfo userInfo3= new UserInfo(3,"李四","user");
// UserInfo userInfo4= new UserInfo(4,"王五","user");
// lists.add(userInfo1);
// lists.add(userInfo2);
// lists.add(userInfo3);
// lists.add(userInfo4);
// adapter = new BaseRecycleViewAdapter(lists,R.layout.layout_user_item,BR.userInfo);
// adapter.setListener(new BaseRecycleViewAdapter.OnItemClickListener() {
// @Override
// public void onItemClick(ViewDataBinding dataBinding, int position) {
// }
// });
// bing.recyclerView.setAdapter(adapter);
// }
/**
* 自定义事件Handler
*/
public class MyEventHandler {
public void onClick(View view) {
switch (view.getId()) {
case R.id.btnGetType: {
Toast.makeText(MainActivity.this, orderInfo.getRescueName(), Toast.LENGTH_SHORT).show();
break;
}
}
}
public void getUser(UserInfo userInfo) {
Toast.makeText(MainActivity.this,"id:" + userInfo.id.get() + ",name:" + userInfo.name.get() + ",type:" +userInfo.type.get() ,Toast.LENGTH_SHORT).show();
}
}
}
一、Binding
在MainActivity我们先不看别的,我们看见了一个ActivityMainBinding的类,看这个类名就大概能猜到这个类是与data binding框架相关的,但是究竟是何种关系呢?实际上呢,ActivityMainBinding就是根据layout文件编译生成的,也就相当于一个layout转化的一个Java类,下面我们来看看它的转换规则。
首先我们看看它的命名规则,这个我们新建以后自动生成的layout文件叫做activity_main.xml,而我们自动生成的Binding类叫ActivityMainBinding,生成的规则是以下划线作为分割线,首字母变成大写,以Binding结尾,Binding类的存放是在app\build\generated\source\apt\debug\com\wshuttle\trailerplatform\databinding的路径下的。
我们再看看Binding类内部的生成规则。Binding类会对在layout中data节点下定义的变量都生成一个私有的变量值,并为它生成get和set的方法,方便我们直接对变量进行赋值;会对layout中有id的控件生成一个public的变量,可如同代码中bing.listView获取layout的listview,并且控件的类型获取时已经确定了, 不再需要强制转换等任何的操作。
以下是Binding类生成的变量
private static final android.databinding.ViewDataBinding.IncludedLayouts sIncludes;
private static final android.util.SparseIntArray sViewsWithIds;
static {
sIncludes = null;
sViewsWithIds = new android.util.SparseIntArray();
sViewsWithIds.put(R.id.toolbar, 10);
sViewsWithIds.put(R.id.listView, 11);
}
// views
public final android.widget.Button btnGetName;
public final android.widget.Button btnGetType;
public final android.widget.ListView listView;
private final android.widget.LinearLayout mboundView0;
private final android.widget.EditText mboundView1;
private final android.widget.EditText mboundView3;
private final android.widget.TextView mboundView6;
private final android.widget.TextView mboundView7;
private final com.facebook.drawee.view.SimpleDraweeView mboundView8;
private final android.widget.ImageView mboundView9;
public final android.support.v7.widget.Toolbar toolbar;
public final android.widget.EditText username;
// variables
private wshuttle.com.testmvvm.bean.OrderInfo mOrderInfo;
private android.databinding.ObservableInt mImageUrl;
private wshuttle.com.testmvvm.bean.UserInfo mUserInfo;
private android.databinding.ObservableBoolean mShow;
private wshuttle.com.testmvvm.ui.MainActivity.MyEventHandler mMyEventHandler;
private final android.view.View.OnClickListener mCallback1;
// values
// listeners
private OnClickListenerImpl mAndroidViewViewOnCl;
现在看来是不是好像有点感觉了?我们直接bing.get或.就可以直接获取layout中绑定的变量以及界面上的控件,我们根本无需再使用注解框架去对界面上的控件进行获取,直接.就可以获取到,是不是很方便啦, 而且再也不担心什么ClassCast失败了,因为你.的时候已经帮你确定了你获取的什么控件。注意:data binding在实际的开发过程中,由于要根据你敲写的代码然后再生成Binding类,有时候你在layout已经书写完了的id或者变量可能在Activity会出现错误,但是没关系,如果你直接运行的话没错误的话就可以了,或者尝试rebuild project(本人觉得比较耗时)
二、activity的setContentView
在以上代码上我们是不是没看见setContentView(R.layout.activity_main);但是我们可以发现代码中有一句
bing = DataBindingUtil.setContentView(this, R.layout.activity_main);
这句话实际上与setContentView(R.layout.activity_main);是相同的。注意的是DataBindingUtil是data binding中的一个工具类,可以用于进行设置activity、获取layout等的操作,它的setContextView的方法第一个参数就是你要展示的activity对象、第二个参数就是layoutid啦。
三、activity与layout的交互
以上介绍了Binding的生成规则、setContextView,下面就是重点–activity与layout的交互。看代码中我们定义了一下字段与界面上定义的变量进行一一对应
public ObservableBoolean show = new ObservableBoolean();
public ObservableInt imageUrl = new ObservableInt(R.mipmap.ic_launcher);
private OrderInfo orderInfo;
,之前在上一篇Android databinding详解(一)–layout解析我们定义的这些了变量,在activity我们定义以上三个字段与之形成对应,实际上就是赋值到layout中,这样子我们改变了activity中的这几个变量就会改变layout中的变量,然后便会刷新界面(记住上节讲的要定义Observable或者执行bing.notifyPropertyChanged(BR.对应的字段))。实际上我们也可以不定义变量,但是就必须每次改变值都调用bing.set的方法,在这里我比较喜欢定义变量来处理layout的数值,看个人喜好咯。
定义了变量以后自然就是设置到layout中了,看官请看以下代码
show.set(true);
bing.setShow(show);
bing.setUserInfo(new UserInfo());
bing.setMyEventHandler(new MyEventHandler());
bing.setOrderInfo(orderInfo);
bing.setImageUrl(imageUrl);
以上我们看见,第一句是对定义的show进行赋值,show不是简单的boolean类型,是一个ObservableBoolean它实际上是一个引用类型,所以赋值需要set进去。后面几句是我们将activity和layout的变量进行关联起来,在上一篇中我们设置的userInfo是执行了双向绑定的,其他的都是单向进行绑定的。
以上的工作都做完了以后就是要执行我们的逻辑了,在这里我们实现的只是单击获取orderInfo的值、单击获取输入的内容、三秒更改orderInfo的信息查看界面有无改变。handler.postDelayed我们三秒后修改了orderInfo的信息的内容以及show的值,根据在layout我们设置的逻辑,orderInfo修改后,界面上展示的信息真的改变了,还有show改变后,一个imageView也消失不见了;单击获取车主姓名以后,我们可以看见提示的也是修改后的orderInfo的信息;单击获取用户信息以后,我们可以看见name,type的值都提示输入的信息,但是由于id没有执行双向绑定维持的是默认值0。
四、总结
看起来是不是很神奇,在layout执行了一部分逻辑,在Activity中绑定变量,直接获取控件等等。实际上data binding还有很多其他的好处,比如说自定义属性,其实在文章中我们并没有解释如何绑定imageview,其实绑定imageview我们使用的就是自定义的属性,这个将在下一篇文章中进行解析,实现透露这个方法叫做bindAdapter,等等。
到现在为止我们已经知道了data binding的基本原理以及一系列的操作,今后的章节将会补充一些其他方面的知识,bindAdapter(自定义属性)、自定义控件(更简单)、与RecyclerView的结合使用、一系列基类的定义等等。