上一篇介绍了mvp的实现思路,这里介绍android原生自带的数据绑定框架的使用。对于的官方工程也是放在mvp简介的介绍页面里的,html
对应的官方Data Binding示例地址为:https://github.com/googlesamples/android-architecture/tree/todo-databinding/java
也能够查看官方关于Data Binding 库的说明:http://developer.android.com/tools/data-binding/guide.html#data_objectsandroid
安卓的实现一个界面,正常的作法是新建一个Activity类,新建一个layout文件,在Activity的setContentView(R.layout.xxxxx);把Activity类与layout布局绑定,而后使用findViewById(R.id.xxxx)找到指定控件,而后对控件作相应的操做,对于列表控件显示也是大概相同的流程,都是View view = LayoutInflater.from(Context()).inflate(R.layout.xxx, viewGroup, false);找到父容器控件后再View.findViewById(R.id.xxx)找到具体的控件,对其进行相应的设置。git
Data Binding 库能实现的功能是在layout布局文件定义时,就指定了数据与控件的绑定和界面事件的处理。省去了必须findViewById的麻烦,以及更好的作到数据与界面的分离。github
1.控件与数据的绑定,在layout里指定控件的一些属性怎样与指定的数据绑定app
android:text="@{task.title}"框架
代替以往的。((EditText)findViewById(R.id.add_task_title)).setText(task.getTitle());ide
<EditText android:id="@+id/add_task_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/title_hint" android:text="@{task.title}" android:singleLine="true" android:textAppearance="@style/TextAppearance.AppCompat.Title" />
android:visibility="@{stats.showStatus ? View.VISIBLE : View.GONE}"工具
代替以往的findViewById(R.id.add_task_title).setVisibility(task.showStatus?View.VISIBLE: View.GONE);布局
<TextView android:layout_width="match_parent" android:layout_height="match_parent" android:text="@{stats.status}" android:textAppearance="?android:attr/textAppearanceMedium" android:visibility="@{stats.showStatus ? View.VISIBLE : View.GONE}" />
android:background="@{task.isCompleted?@drawable/list_completed_touch_feedback: @drawable/touch_feedback}"
代替以往的 View.setBackgroundResource(task.isCompleted?R.drawable.xxx: R.drawable/xx);
<LinearLayout android:layout_width="match_parent" android:layout_height="?android:attr/listPreferredItemHeight" android:background="@{task.isCompleted ? @drawable/list_completed_touch_feedback : @drawable/touch_feedback}" android:orientation="horizontal" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingBottom="@dimen/list_item_padding" android:paddingTop="@dimen/list_item_padding" android:onClick="@{() -> actionHandler.taskClicked(task)}">
2.控件与方法的绑定,在layout里指定控件的一些点击接口或其余回调接口怎样与对应的方法绑定。
android:onClick="@{() -> actionHandler.taskClicked(task)}"
代替View.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
<LinearLayout android:layout_width="match_parent" android:layout_height="?android:attr/listPreferredItemHeight" android:background="@{task.isCompleted ? @drawable/list_completed_touch_feedback : @drawable/touch_feedback}" android:orientation="horizontal" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingBottom="@dimen/list_item_padding" android:paddingTop="@dimen/list_item_padding" android:onClick="@{() -> actionHandler.taskClicked(task)}">
如何使用Data Binding 库
1.开发环境:
compileSdkVersion 25
buildToolsVersion "25.0.2"
classpath 'com.android.tools.build:gradle:2.3.0'
并不须要根项目声明apt插件,
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
也不须要在模块里
apply plugin: 'com.neenbedankt.android-apt'
只须要在用到的模块下加入下面语句。
dataBinding { enabled = true }
2.1用于与界面绑定数据的java
新建Java类,并继承 android.databinding.BaseObservable,把须要在layout布局里引用的方法,加上@Bindable注解或@BindingAdapter, 使用@Bindable注解过的方法能够直接使用在xml布局里,以下面定义的getName()方法,能够在layout里这样使用
android:text='@{"name:"+company.getName()}'
public class Company extends BaseObservable{ ......省略若干代码 @BindingAdapter({"bind:imageUrl", "bind:error"}) public static void setIcon(ImageView view, String url, Drawable error) { Glide.with(view.getContext()).load(url).error(error).into(view); } @Bindable public String getName() { return name; } ......省略若干代码 }
若是layout里须要用到一些工具类里的静态方法,不须要继承BaseObservable,也不须要在方法前增长注解。
public class DateUtil{ ......省略若干代码 public static String getTime(long time) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); return sdf.format(time); } ......省略若干代码 }
2.2 用于与控件绑定事件的类,不须要使用注解。像普通的java类同样定义便可。
public class ActionHandler { private Context mContext; public ActionHandler(Context context) { this.mContext = context; } public void showTextDialog(String text) { new AlertDialog.Builder(mContext).setTitle("detail") .setMessage(text).create().show(); } }
在layout里便可调用:android:onClick="@{(tv)->actionHandler.showTextDialog(company.toString())}"
3.定义layout布局
不使用Data Binding 库的layout布局以下。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.databindtest.MainActivity">
......省略若干代码
</LinearLayout>
使用Data Binding库须要以layout为根标签,并加入一个data子标签,
data标签里经常使用到的有variable和import标签,
variable标签引入的是一个须要在java代码里动态设置的对象,type字段是Java类的导入,至关于代码里的import android.databinding.BaseObservable;
name字段至关于变量名称。
当data标签里有以下的一段代码时,
<variable name="company" type="com.example.databindtest.Company" />
当自动生成的Data Binding对象会生成一个setCompany(com.example.databindtest.Company c)的方法
import 标签通常是声明须要引用一些工具类里的里的静态方法。
和一些用到的类型,若是app:error="@{@drawable/ic_launcher'}" 就须要先声明Drawable。
不管是绑定数据仍是事件方法,都是找到对象而后调用相应的get方法或事件方法。
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:app="http://schemas.android.com/apk/res-auto"> <data> <variable name="company" type="com.example.databindtest.Company" /> <variable name="actionHandler" type="com.example.databindtest.ActionHandler" /> <import type="android.graphics.drawable.Drawable" /> <import type="com.example.databindtest.DateUtil" /> </data> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/company_item_root_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/cardview_dark_background" android:padding="8dp"> <android.support.v7.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="8dp"> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.CardView android:id="@+id/cv_wrap" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="8dp"> <ImageView android:id="@+id/iv_icon" android:layout_width="80dp" android:layout_height="80dp" android:minHeight="80dp" android:minWidth="80dp" android:layout_centerVertical="true" android:onClick="@{(tv) -> actionHandler.showImageDialog(company.getIcon())}" app:error="@{@drawable/ic_launcher'}" app:imageUrl="@{company.getIcon()}" /> </android.support.v7.widget.CardView> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="8dp" android:layout_marginTop="8dp" android:layout_toRightOf="@id/cv_wrap" android:orientation="vertical"> </LinearLayout> </RelativeLayout> </android.support.v7.widget.CardView> </FrameLayout> </layout>
作完上面的工做后,已经准备好了数据实体对象和layout布局,若是这时候使用了android studio的Build->Make Module 'xxx'的编译某个模块的功能,若是没有编译出错,能够看到在相应的临时编译生成了对应的xxxBinding文件,以下图所示
只须要在Activity里简单的调用几句,就能够实现数据自动填充到View,而且绑定控件的事件处理方法。
调用 Binding.setCompany(mCompany);会自动把数据填充到View上。
package com.example.databindtest; import android.content.Context; import android.databinding.DataBindingUtil; import android.support.annotation.Nullable; import android.support.v4.app.DialogFragment; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.DividerItemDecoration; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.EditText; import com.example.databindtest.databinding.CompanyItemLayoutBinding; import java.util.List; public class MainActivity extends AppCompatActivity { private Company mCompany; CompanyItemLayoutBinding mBinding; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mBinding = DataBindingUtil.bind(findViewById(R.id.company_item_root_layout)); mCompany = Company.getCompanyList().get(0); mBinding.setActionHandler(new ActionHandler(this)); mBinding.setCompany(mCompany); initView(); } //......省略若干代码 public void setting(View view) { mCompany.setIcon(((EditText)findViewById(R.id.et_company_icon_path)).getText().toString()); mCompany.setName(((EditText)findViewById(R.id.et_company_name)).getText().toString()); mCompany.setInfo(((EditText)findViewById(R.id.et_company_info)).getText().toString()); mBinding.setCompany(mCompany); } //......省略若干代码 }
完整代码请查看