您的位置:首页 > 移动开发 > Android开发

开源数据绑定框架android-databinding与google databinding对比

2016-03-21 18:55 453 查看

开源数据绑定框架android-databinding与google databinding对比

0,前言:

google databinding: 指google 2015 io大会后出的数据绑定框架.

android-databinding: 指 heaven7所出的android开源数据绑定框架。

github地址: https://github.com/LightSun/android-databinding

1, 先说下 数据绑定 (思想都是一样的,类似javaweb数据绑定)。

优点:

1) , 大量减少 findViewById,setBackgroundColor, setImageBitmap,setText,setTextColor 等方法

的调用。

2), 减轻Activity的代码负担,使得使用者不用复杂的设计模式即可使得代码变得清晰,可读性也很强,

易于维护。

缺点:

一旦数据绑定相关的方法名或者字段名修改后,数据绑定配置文件也得跟着修改。

多牺牲一些内存。

2, 对比google官方的databinding-library

【google databinding 优点】:

1), 相关的部分代码自动生成(as支持)。 —-> 本框架目前只有简单的as插件

2), 不需要在layout中定义id(但是由于业务的复杂性,很多地方仍然需要定义id).

(本框架放置在res/raw目录下。)

3), 更加丰富的Java表达式的支持。(本框架支持相对弱点,但是足够使用)

google: 所有运算符及嵌套均支持,支持所有java 表达式(除开this,super,new,Explicit generic

invocation)。支持android资源引用..

本框架:java字段、方法和数组的调用(可嵌套)。以及1次3元运算符(不支持其他运算符,

如果你非要用建议以静态方法的方式调用 )。亦支持android资源引用.

4), 相对清晰轻量的架构 。

google databinding的原代码见:

sdk\sources\android-23\android\databinding包。

【Google databinding 缺点】:

1), 数据绑定的配置在对应的layout文件中,会影响布局文件的可读性。尤其的布局复杂之后。

(大家都懂的).

2), 图片边框/圆角/placeholder等不直接支持。

3), 需要手动写RecyclerView等的adapter

【本框架具有,google databinding不具有的】:

1),一般的,不需要你写 listView/GridView/RecyclerView的

adapter.(框架内部自动帮你完成的)

2)更加丰富的事件绑定支持,事件绑定传递自定义参数(包括adapter item事件 绑定).

什么意思呢? Eg:….

3), 图片圆角,边框,圆形等的支持。

3, 具体使用对比(代码)

(1), 基本绑定.

google databinding:

public class Student {
private String name;
private String addr;
public Student() {
}
public Student(String name, String addr) {
this.name = name;
this.addr = addr;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddr() {
return this.addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
}
//布局文件如下
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="stu"
type="org.loader.androiddatabinding.Student" />
</data>

<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{stu.name}"/>

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{stu.addr}"/>
</LinearLayout>
</layout>
//调用代码
public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(
this,R.layout.activity_main);
binding.setStu(new Student("loader", "干锅排骨"));
}
}


Android-databinding :

//布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
tools:context=".MainActivity"
android:orientation="vertical"
>
<Button
android:id="@+id/bt"
android:text="@string/hello_world"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:padding="5dp"
/>
</LinearLayout>

//数据绑定配置文件
<DataBinding
xmlns = "http://schemas.android.com/heaven7/android-databinding/1"
version="1.0"
>
<data>
<variable name="user"  classname="com.heaven7.databinding.demo.bean.User"
type="bean"/>
<variable name="mainHanlder"
classname="com.heaven7.databinding.demo.callback.MainEventHandler"
type="callback"/>
<import classname="android.view.View" alias="View"/>
</data>
// 绑定文本,文本颜色,背景颜色
<bind id="bt">
<property name="text" referVariable="user" >@{user.username}</property>
<property name="textColor" referVariable="user" >user.male ? {@color/red}
:{@color/random}</property>
<property name="backgroundColor" referVariable="user" >#00ff00</property>
</bind>
</DataBinding>
//调用示例代码:
DataBinder.getDataBinder(this, R.raw.db_main,false)
.bind(R.id.bt, true, mUser = new User("heaven7", false));


2), 事件绑定:

google databinding:

//布局文件
<layout xmlns:android="http://schemas.android.com/apk/res/android">

<data>
<import type="org.loader.app3.EventHandlers" />
<variable
name="handlers"
type="EventHandlers" />
</data>

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="CLICK ME"
android:onClick="@{handlers.handleClick}"/>
</LinearLayout>
</layout>
// 事件处理类
public class EventHandlers {
public void handleClick(View view) {
Toast.makeText(view.getContext(), "you clicked the view",
Toast.LENGTH_LONG).show();
}
}


android-databinding:

//布局文件
<Button
android:id="@+id/bt0"
android:text="@string/change_data_by_handler"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:padding="5dp"
/>
//数据绑定配置文件
<DataBinding
xmlns = "http://schemas.android.com/heaven7/android-databinding/1"
version="1.0"
>
<data>
<variable name="user"  classname="com.heaven7.databinding.demo.bean.User"
type="bean"/>
<variable name="mainHanlder"
classname="com.heaven7.databinding.demo.callback.MainEventHandler"
type="callback"/>
<import classname="android.view.View" alias="View"/>
</data>
//**绑定的点击事件和长按点击事件**
<bind id="bt0">
<property name="onClick" referVariable="user,mainHanlder" >
mainHanlder.onClickChangeUsername(user) </property>
<property name="onLongClick" referVariable="user,mainHanlder" >
mainHanlder.onLongClickChangeUsername(user)</property>
</bind>
</DataBinding>

//调用相关代码
@DatabindingClass
public class MainEventHandler extends EventContext{

public MainEventHandler(IDataBinder binder) {
super(binder);
}

@DatabindingMethod
public void onClickChangeUsername(View v,User user){
Util.changeUserName(user,"by_MainEventHandler_OnClick");

//change male
user.setMale(!user.isMale());
getDataBinder().notifyDataSetChanged(R.id.bt);
}

@DatabindingMethod
public void onLongClickChangeUsername(View v,User user){
Toast t =  Toast.makeText(v.getContext(),
"------------ onLongClick ---------", Toast.LENGTH_SHORT);
t.setGravity(Gravity.CENTER, 0, 0);
t.show();
Util.changeUserName(user, "by_MainEventHandler_OnLongClick");

getDataBinder().notifyDataSetChanged(R.id.bt, PropertyNames.TEXT);
}
}

DataBinder.getDataBinder(this,R.raw.db_main,false))
.bind(R.id.bt0, false, mUser,new MainEventHandler(mDataBinder))


3),图片的绑定

Google databinding:

//布局文件:
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
>
<data class=".Custom">
<variable
name="imageUrl"
type="String" />
</data>
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:image="@{imageUrl}"/>
</layout>
//调用相关代码
public class Utils {
@BindingAdapter({"bind:image"})
public static void imageLoader(ImageView imageView, String url) {
ImageLoaderUtils.getInstance().displayImage(url,
);
}
}
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
org.loader.app8.Custom binding = DataBindingUtil.setContentView(this,
R.layout.activity_main);
binding.setImageUrl("http://images.csdn.net/20150810/Blog-
Image%E5%89%AF%E6%9C%AC.jpg");
}
}


android-databinding:

//布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">

<com.android.volley.extra.ExpandNetworkImageView
android:id="@+id/eniv2"
android:layout_width="match_parent"
android:layout_height="200dp"
android:scaleType="centerCrop"
/>
</LinearLayout>

//数据绑定配置文件
<DataBinding
xmlns = "http://schemas.android.com/heaven7/android-databinding/1"
version="1.0"
>
<data>
<variable name="imageParam"         classname="com.heaven7.databinding.demo.samples.RoundImageBindTest$ImageParam"
type="bean"/>
<variable name="eventHandler"               classname="com.heaven7.databinding.demo.samples.RoundImageBindTest$ClickHandler"
type="callback"/>
<import classname="com.heaven7.databinding.demo.test.Test" alias="Test"/>
</data>

//点击事件, 图片url,圆角,边框,默认图,错误图的配置
<bind id="eniv2">
<property name="onClick" referVariable="eventHandler" >
eventHandler.onClickImage()</property>
<imageProperty type="round" referVariable="imageParam">
<roundSize>{@dimen/corner_size}</roundSize>
<borderWidth>5dp</borderWidth>
<borderColor>#ff0000</borderColor>

<url>imageParam.link</url>
<default>{@drawable/ic_default}</default>
<errorResId>R.drawable.ic_error</errorResId>
</imageProperty>
</bind>
</DataBinding>

//调用相关代码
public class RoundImageBindTest extends BaseActivity {

@Override
protected int getBindRawId() {
return R.raw.db_round_image_test;
}
@Override
protected int getlayoutId() {
return R.layout.activity_round_image_test;
}
@Override
protected void onFinalInit(Bundle savedInstanceState) {
}
@Override
protected void doBind() {
mDataBinder.bind(R.id.eniv2, false, new ImageParam(
Test.URLS[1]),new ClickHandler(getToaster()) );
}

public static class ImageParam{
float roundSize;
@DatabindingField
String url;
String link;
public ImageParam(float roundSize, String url) {
this.roundSize = roundSize;
this.url = url;
}
public ImageParam(String link) {
this.link = link;
}
}
public static class ClickHandler{

private final Toaster mToaster;
public ClickHandler(Toaster mToaster) {
this.mToaster = mToaster;
}
public void onClickImage(View v){
mToaster.show("---------  onClickImage  ------------");
}
}
}


4), ListView / RecyclerView / GridView adapter数据的绑定

Google databinding:

//item 布局文件
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="stu"
type="org.loader.app6.Student" />
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{stu.name}"
android:layout_alignParentLeft="true"/>

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{String.valueOf(stu.age)}"
android:layout_alignParentRight="true"/>
</RelativeLayout>
</layout>

//adapter代码
private class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private ArrayList<Student> mData = new ArrayList<>();

private MyAdapter(ArrayList<Student> data) {
mData.addAll(data);
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
ViewDataBinding binding = DataBindingUtil.inflate(LayoutInflater
.from(viewGroup.getContext()), R.layout.item, viewGroup, false);
ViewHolder holder = new ViewHolder(binding.getRoot());
holder.setBinding(binding);
return holder;
}

@Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
viewHolder.getBinding().setVariable(org.loader.app6.BR.stu,
mData.get(i));
viewHolder.getBinding().executePendingBindings();
}

@Override
public int getItemCount() {
return mData.size();
}

class ViewHolder extends RecyclerView.ViewHolder {
private ViewDataBinding binding;
public ViewHolder(View itemView) {
super(itemView);
}
public void setBinding(ViewDataBinding binding) {
this.binding = binding;
}
public ViewDataBinding getBinding() {
return this.binding;
}
}
}
//调用主要代码
private RecyclerView mRecyclerView;
private ArrayList<Student> mData = new ArrayList<Student>() {
{
for (int i=0;i<10;i++) add(new Student("loader" + i, 18 + i));
}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

mRecyclerView = (RecyclerView) findViewById(R.id.recycler);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this,
LinearLayoutManager.VERTICAL, false));
mRecyclerView.setAdapter(new MyAdapter(mData));
}


android-databinding:

//item布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
>
<com.android.volley.extra.ExpandNetworkImageView
android:id="@+id/eniv"
android:layout_width="match_parent"
android:layout_height="200dp"
android:scaleType="centerCrop"
/>

<TextView
android:id="@+id/tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:padding="10dp"
/>
</LinearLayout>
//数据绑定配置文件
?xml version="1.0" encoding="utf-8"?>
<DataBinding
xmlns = "http://schemas.android.com/heaven7/android-databinding/1"
version="1.0"
>
<data>
<variable name="imageInfo"
classname="com.heaven7.databinding.demo.bean.ImageInfo"  type="bean"/>
<variable name="itemHandler"           classname="com.heaven7.databinding.demo.samples.ListViewBindAdapterTest$ItemHandler"
type="callback"/>
</data>

<bindAdapter id="rv" referVariable="imageInfo" selectMode="1">
<item layout="item_image"  referVariable="itemHandler">
<property name="onClick" >itemHandler.onItemClick()</property>
<bind id="tv">
<property name="text" >imageInfo.desc</property>
<property name="textColor" >imageInfo.isSelected() ?
{@color/red} : {@color/random}</property>
<property name="onClick" >itemHandler.onTextClick()</property>
</bind>
<bind id="eniv">
<property name="img_url" >imageInfo.url</property>
</bind>
</item>
</bindAdapter>
</DataBinding>

//调用主要代码
public class RecycleViewBindAdapterTest extends BaseActivity {

AdapterManager<ImageInfo> mAM;

@Override
protected int getBindRawId() {
return R.raw.db_test_simple_recycle_view;
}
@Override
protected int getlayoutId() {
return R.layout.activity_recycle_view;
}

@Override
protected void onFinalInit(Bundle savedInstanceState) {
RecyclerView rv = (RecyclerView) findViewById(R.id.rv);
rv.setLayoutManager(new LinearLayoutManager(
this,LinearLayoutManager.VERTICAL,false));
}
@Override
public void doBind() {
List<ImageInfo> infos = new ArrayList<>();
for(int i=0 , size = Test.URLS.length ; i < size  ;i++){
infos.add(new ImageInfo(Test.URLS[i],"desc_"+i));
}
//ItemHandler 是item的事件处理器
mAM = mDataBinder.bindAdapter(R.id.rv, infos,
new ListViewBindAdapterTest.ItemHandler(
getToaster()));
}
}
//ItemHandler代码
public static class ItemHandler {
private final Toaster mToaster;
public ItemHandler(Toaster mToaster) {
this.mToaster = mToaster;
}

public void onItemClick(View v, Integer position,ImageInfo item,
AdapterManager<?> am){
mToaster.show("ItemHandler_onItemClick: position = " +
position + " ,item = " + item);
if(item.isSelected()){
am.getSelectHelper().setUnselected(position);
}else{
am.getSelectHelper().setSelected(position);
}
}
public void onTextClick(View v, Integer position,ImageInfo item,
AdapterManager<?> am){
mToaster.show("on text click: position = " + position +
" ,item = " + item);
}
}


4, 小结.

个人感觉本框架还是不错的,不过还有些地方待完善。

比如带运算符表达式的支持,代码自动生成(预计后面将会支持)。手势图片(即将支持).

Google毕竟有官方固定的人力支持,而android-databinding目前就1个人负责维护. ~~~~

诚心邀请有意愿想为开源做贡献的朋友来参加,把这个项目做得更好,更完善。

备注: 以上示例

Google databinding主要来自:/article/1915082.html

Android-databinding 来自: https://github.com/LightSun/android-databinding 的sample

不知道这是什么? 参见我之前写的博客: /article/8818387.html.

或者直接进入Github ,主页有相关文档(中文版or英文版)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: