记录DataBinding使用
例一
MainActivity
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//会根据布局文件自动生成布局文件名开头的Binding类
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
User user = new User(this,"Test", "User",true);
binding.setUser(user);
}
}
User
public class User {
public final String firstName;
public final String lastName;
public Context context;
public boolean isFriend;
public User(Context context,String firstName, String lastName,boolean isFriend) {
this.context=context;
this.firstName = firstName;
this.lastName = lastName;
this.isFriend=isFriend;
}
}
XML
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="user"
type="com.example.yaoyan.databinding.User" />
</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.firstName}"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.lastName}"/>
</LinearLayout>
</layout>
例二 绑定事件
MainActivity
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//会根据布局文件自动生成布局文件名开头的Binding类
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
User user = new User(this,"Test", "User",true);
binding.setUser(user);
binding.setHandlers(new MyHandlers());
}
}
User类没变
XML
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="handlers"
type="com.example.yaoyan.databinding.MyHandlers" />
<variable
name="user"
type="com.example.yaoyan.databinding.User" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{user.isFriend ? handlers.onClickFriend : handlers.onClickEnemy}"
android:text="@{user.firstName}" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{user.isFriend ? handlers.onClickEnemy : handlers.onClickFriend }"
android:text="@{user.lastName}" />
</LinearLayout>
</layout>
例三 导入类
<data>
<import type="android.view.View"/>
</data>
<Button
android:visibility="@{View.INVISIBLE}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
例四 List数组
MainActivity
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//会根据布局文件自动生成布局文件名开头的Binding类
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
List<String> list=new ArrayList<>();
list.add("aaa");
binding.setUserList(list);
}
}
XML
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<import type="java.util.List" />
<variable
name="userList"
type="List<String>" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{userList[0].toLowerCase()}" />
</LinearLayout>
</layout>
其中特别注意一点,在@{}表达式中不支持左括号,所以我们需要用转义字符代替左括号
例五 静态
public class Teacher {
public static String GG(){
return "1111111";
}
}
<data>
<import type="com.example.yaoyan.databinding.Teacher"></import>
</data>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{Teacher.GG()}" />
例六 变量
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//会根据布局文件自动生成布局文件名开头的Binding类
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
binding.setUserList("尼玛");
}
}
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="userList"
type="String" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{userList}" />
</LinearLayout>
</layout>
和 Java 一样,java.lang.* 会被自动导入。
例七 调用方法
public class User {
public final String firstName;
public final String lastName;
public List<User> list=new ArrayList<User>();
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String ggg(String st){
System.out.println("st = " + st);
return "asdas";
}
}
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//会根据布局文件自动生成布局文件名开头的Binding类
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
binding.setUserList(new User("111","222"));
}
}
<Button
android:text='@{userList.ggg("123")}'
android:textAllCaps="false"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<data>
<variable
name="userList"
type="com.example.yaoyan.databinding.User" />
</data>
例八 Context对象
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//会根据布局文件自动生成布局文件名开头的Binding类
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
binding.setUserList(new User("111","222"));
}
}
public class User {
public final String firstName;
public final String lastName;
public List<User> list=new ArrayList<User>();
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String ggg(Context context){
Toast.makeText(context,"toast",Toast.LENGTH_LONG).show();
return "asdas";
}
}
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="userList"
type="com.example.mac.studybinding.User" />
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:text='@{userList.ggg(context)}'
android:textAllCaps="false"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</layout>
binding 类会生成一个命名为context的特殊变量(其实就是 rootView 的 getContext())的返回值),这个变量可用于表达式中. 如果有名为context的变量存在,那么生成的这个context特殊变量将被覆盖.
例九 可以在表达式中直接引用带id的view,引用时采用驼峰命名法.
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="userList"
type="com.example.mac.studybinding.User" />
<import type="android.view.View"></import>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/yaoyan_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{userList.firstName}" />
<TextView
android:text="@{userList.lastName}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="@{yaoyanName.getVisibility() == View.GONE ? View.VISIBLE : View.GONE}" />
</LinearLayout>
</layout>
这里TextView直接引用第一次TextView,yaoyanName为id的驼峰命名
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//会根据布局文件自动生成布局文件名开头的Binding类
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
binding.setUserList(new User("111","222"));
}
}
public class User {
public final String firstName;
public final String lastName;
public List<User> list=new ArrayList<User>();
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String ggg(String st){
System.out.println("st = " + st);
return "asdas";
}
public String ggg(Context context){
Toast.makeText(context,"toast",Toast.LENGTH_LONG).show();
return "asdas";
}
}
例十 RecyclerView+DataBinding
MainActivity
public class MainActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private List<String> mDatas;
private HomeAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
mRecyclerView = (RecyclerView) findViewById(R.id.id_recyclerview);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mRecyclerView.setAdapter(mAdapter = new HomeAdapter());
}
protected void initData()
{
mDatas = new ArrayList<String>();
for (int i = 1; i < 100; i++)
{
mDatas.add("----" + i);
}
}
class HomeAdapter extends RecyclerView.Adapter<HomeAdapter.MyViewHolder>
{
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
ViewDataBinding binding = DataBindingUtil.inflate(LayoutInflater.from(getApplicationContext()), R.layout.item_home, parent, false);
MyViewHolder holder=new MyViewHolder(binding);
return holder;
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position)
{
ItemHomeBinding binding = (ItemHomeBinding) holder.getBinding();
String s = mDatas.get(position);
Item item=new Item();
item.setS(s);
binding.setVariable(BR.obj, item);
binding.executePendingBindings();
}
@Override
public int getItemCount()
{
return mDatas.size();
}
class MyViewHolder extends RecyclerView.ViewHolder
{
private ViewDataBinding binding;
public MyViewHolder(ViewDataBinding binding)
{
super(binding.getRoot());
this.binding=binding;
}
public ViewDataBinding getBinding() {
return binding;
}
}
}
}
executePendingBindings()方法.这个方法迫使数据立即绑定而不是在下一帧的时候才绑定.RecyclerView会在onBindViewHolder方法执行后立即测量这些view.假设没使用executePendingBindings()方法,由于在下一帧的时候才会绑定,view就会绑定错误的data,测量也会出错.因此,executePendingBindings()是很重要的.
Item
public class Item {
private String s;
public String getS() {
return s;
}
public void setS(String s) {
this.s = s;
}
}
Item_XML
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="obj" type="com.example.mac.databinding.Item"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:background="#44ff0000"
android:layout_height="wrap_content">
<TextView
android:textColor="#000000"
android:id="@+id/id_num"
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center"
android:text="@{obj.s}" />
</LinearLayout>
</layout>
Main_XML
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/id_recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"></android.support.v7.widget.RecyclerView>
</LinearLayout>
</layout>
例十一 自动设置属性
public class MainActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private List<String> mDatas;
private HomeAdapter mAdapter;
private ActivityMainBinding activityMainBinding;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
}
}
public class myView extends LinearLayout {
public myView(Context context) {
super(context);
}
public myView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public myView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public myView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
// 自动 Setter
public void setObject(String u) {
System.out.println("myView.setObject");
}
}
<?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">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.mac.databinding.myView
android:id="@+id/aaa"
<!--app:方法 实际是调用的setObject(String u) -->
app:object='@{"123"}'
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</layout>
例十二 Observable
当表达式引用了一个类内的属性时,他会尝试直接调用域,getter,还有ObservableFields。
Observable 接口有一个添加/移除 listener 的机制,但通知取决于开发者。为了简化开发,我们创建了一个基类 BaseObservable,来实现 listener ***制。这个类也实现了域变动的通知,你只需要在 getter 上使用 Bindable 注解,并在 setter 中实现通知。
User
public class User extends BaseObservable{
public String firstName;
public String lastName;
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
@Bindable
public String getFirstName() {
return this.firstName;
}
@Bindable
public String getLastName() {
return this.lastName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
notifyPropertyChanged(BR.firstName);
}
public void setLastName(String lastName) {
this.lastName = lastName;
notifyPropertyChanged(BR.lastName);
}
}
MainActivity
public class MainActivity extends AppCompatActivity {
private List<String> mDatas;
private ActivityMainBinding activityMainBinding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
User u=new User("123","456w");
activityMainBinding.setUser(u);
}
}
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>
<variable
name="user"
type="com.example.yaoyan.databinding.User"></variable>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:id="@+id/et_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text='@={user.firstName}' />
<TextView
android:id="@+id/et_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text='@{user.firstName}' />
</LinearLayout>
</layout>
例十二 重命名属性设置
一些属性的命名与 setter 不对应,针对这些函数,可以用 BindingMethods注解来将属性与setter绑定在一起.举个例子:android:tint属性可以这样与setImageTintList(ColorStateList) ) 绑定,而不是 setTint :