开源数据绑定框架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英文版)
相关文章推荐
- Android一个应用(APK)多个入口的实现方式整理
- android性能测试工具之dumpsys
- 关于Animation类中的方法setRepeatCount(int)方法使用
- Android源码 · IBinder
- Android 开发过程遇到的错误和总结
- Android笔记——六大布局
- 在Android中使用Gradle
- [Android4.4.3] Nubia Z5S Mokee4.4.3 RC2.0 by syhost
- activity window 获取setContentView的基视图(getContentView)
- Android Support Library
- Android Studio 遇到的错误、异常和总结
- Android RecyclerView 使用完全解析 体验艺术般的控件
- Android官方开发文档Training系列课程中文版:构建第一款安卓应用之创建用户界面
- Android-Android studio加载9.png图片报错
- android之socket编程(二)案例
- 基于android的Socket通信(一)原理
- Android NestedScrolling嵌套滑动机制
- Intent详解
- Android Volley完全解析(一),初识Volley的基本用法
- Android自定义控件之自定义TextView,实现drawableLeft可以和文字一起居中