分享

android黑科技——完美解决界面逻辑的数据框架DataBinding(最新)的使用(二)

 guitarhua 2017-08-13

昨天我们一起学习了dataBinding的基础用法,我想你可能还停留在它只是不用再findViewById,其实不然,今天我们就来扩展延伸,看看这个框架到底有什么魔力让谷歌官方大力推崇。这里还没看昨天的基础运用的需要去看一看,附上链接:http://www.cnblogs.com/liushilin/p/5681473.html

项目已经同步至github:https://github.com/nanchen2251/databinding

昨天我们解决了简单的使用以及在xml中进行属性的变换和一些简单的表达式放在xml文件中的使用问题,大家肯定有所疑问,我们在实际开发中肯定会用到很多的布局重用等,那么在这个框架中可否同样做到呢?另外,如果我们想用这个框架实现图片加载呢?大家都知道图片在xml中只能通过src设置本地图片,并没有提供通过url设置的属性,别急,楼主会把这个方法分享给你。

1)首先把昨天的xml代码放到一个独立的xml文件中,楼主这里叫user_layout.xml,这里设置图片通过使用app自定义属性设置图片url

复制代码
1 2 layout 3 xmlns:android='http://schemas./apk/res/android' 4 xmlns:tools='http://schemas./tools' 5 xmlns:app='http://schemas./apk/res-auto'> 6 7 variable 8 name='user' 9 type='com.example.nanchen.databindingdemo.User'>10 11 12 13 LinearLayout14 android:layout_width='0dp'15 android:layout_weight = '1'16 android:layout_height='match_parent'17 android:gravity='center'18 android:orientation='vertical'19 tools:context='com.example.nanchen.databindingdemo.MainActivity'>20 21 ImageView22 android:layout_width='100dp'23 android:layout_height='100dp'24 app:imageUrl='@{ user.icon }'/>25 26 TextView27 android:layout_width='wrap_content'28 android:layout_height='wrap_content'29 android:textSize='25sp'30 android:onClick='@{user.clickName}'31 android:textColor='@{user.vip? 0xffff0000:0xff000000}'32 android:text='@{user.nickName + `(` + user.name +`)`}'/>33 34 TextView35 android:layout_width='wrap_content'36 android:layout_height='wrap_content'37 android:textSize='25sp'38 android:onLongClick='@{user.longClickNickName}'39 android:text='@{user.nickName ?? user.name}'/>40 41 TextView42 android:layout_width='wrap_content'43 android:layout_height='wrap_content'44 android:textSize='25sp'45 android:textColor='@{user.level < 3="" 0xff03bbf9="" :="" 0xfff60bdb="">46 android:text='@{user.email}'/>47 48
复制代码

2)然后修改主页面的xml文件,activity_main.xml,由于我们使用的是左右对称显示两个用户,所以我们应该用list,而不是之前的user,其中用到的尖括号用转义方法上一节已经讲过。

复制代码
layout xmlns:android='http://schemas./apk/res/android' xmlns:app='http://schemas./apk/res-auto' xmlns:tools='http://schemas./tools'> import type='com.example.nanchen.databindingdemo.User'/> variable name='users' type='java.util.List'/> LinearLayout android:layout_width='match_parent' android:layout_height='match_parent' android:gravity='center' android:orientation='horizontal' tools:context='com.example.nanchen.databindingdemo.MainActivity'> include layout='@layout/user_layout' app:user='@{ users[0] }'/> include layout='@layout/user_layout' app:user='@{ users[1] }'/>
复制代码

 

3)再改下Activity的代码

复制代码
package com.example.nanchen.databindingdemo;import android.databinding.DataBindingUtil;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import com.example.nanchen.databindingdemo.databinding.ActivityMainBinding;import java.util.ArrayList;import java.util.List;public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);// setContentView(R.layout.activity_main); ActivityMainBinding binding = DataBindingUtil.setContentView(this,R.layout.activity_main); User user = new User(); user.setName('刘世麟'); user.setNickName('南尘'); user.setEmail('liushilin@qq.com'); user.setVip(true); user.setLevel(5); user.setIcon('http://qlogo1.store.qq.com/qzone/503233512/503233512/100?1311741184');// binding.setUser(user); User user1 = new User(); user1.setName('春春儿'); user1.setNickName(null); user1.setVip(false); user1.setEmail('nanchen@qq.com'); user1.setLevel(1);// binding.setUser(user1); List list = new ArrayList<>(); list.add(user); list.add(user1); binding.setUsers(list);// binding.setUser(new User('刘世麟','南尘','liushilin@qq.com')); }}
复制代码

看看运行效果

 

看到这里,也许小伙伴会说,切,不就一个include吗,这个框架还是没带来飞一般的感觉,别急,还有更厉害的使用ListView之类的等着你

我们来看看listView如何实现。

1)自然需要先定义一个list_item.xml,用于基本Item的布局。

复制代码
1 2 3 layout 4 xmlns:android='http://schemas./apk/res/android' 5 xmlns:app='http://schemas./apk/res-auto'> 6 7 8 variable 9 name='user'10 type='com.example.nanchen.databindingdemo.User'/>11 12 13 LinearLayout14 android:layout_width='match_parent'15 android:layout_height='match_parent'16 android:orientation='horizontal'17 android:onClick='@{ user.click }'>18 19 ImageView20 android:layout_width='100dp'21 android:layout_height='100dp'22 app:imageUrl='@{user.icon}'/>23 24 TextView25 android:layout_width='match_parent'26 android:layout_height='match_parent'27 android:text='@{user.name}'28 android:gravity='center'/>29 30 31
复制代码

2)写一个通用的适配器Adaper,注意这里和你以往写的ListView的适配器完全不一样,我们多了两个属性,一个是layoutId,一个是属性id

复制代码
1 package com.example.nanchen.databindingdemo; 2 3 import android.content.Context; 4 import android.databinding.DataBindingUtil; 5 import android.databinding.ViewDataBinding; 6 import android.view.LayoutInflater; 7 import android.view.View; 8 import android.view.ViewGroup; 9 import android.widget.BaseAdapter;10 11 import java.util.List;12 13 /**14 * ListView的通用Adapter15 * Created by 南尘 on 16-7-18.16 */17 public class CommonAdapter extends BaseAdapter {18 private Context context;//上下文环境19 private List list;//通用的,不知道数据20 private int layoutId;//通用的,不知道布局21 private int variableId;//变量的id22 23 /**24 * 构造方法25 */26 public CommonAdapter(Context context, List list, int layoutId, int variableId) {27 this.context = context;28 this.list = list;29 this.layoutId = layoutId;30 this.variableId = variableId;31 }32 33 @Override34 public int getCount() {35 if (list!=null)36 return list.size();37 return 0;38 }39 40 @Override41 public Object getItem(int position) {42 return list.get(position);43 }44 45 @Override46 public long getItemId(int position) {47 return position;48 }49 50 @Override51 public View getView(int position, View convertView, ViewGroup parent) {52 ViewDataBinding binding = null;53 if (convertView == null){54 binding = DataBindingUtil.inflate(LayoutInflater.from(context),layoutId,parent,false);55 }else{56 binding = DataBindingUtil.getBinding(convertView);57 }58 binding.setVariable(variableId,list.get(position));59 return binding.getRoot();60 }61 }
复制代码

3)在xml中布局,这个比较简单,先在配置文件中把这个更改为程序入口,并且添加网络操作权限,这里用了BR文件,BR文件和R文件都是系统会自动生成的,只是R文件用于资源的id。图片我们就使用一个默认的

复制代码
1 package com.example.nanchen.databindingdemo; 2 3 import android.databinding.DataBindingUtil; 4 import android.os.Bundle; 5 import android.support.v7.app.AppCompatActivity; 6 7 import com.example.nanchen.databindingdemo.databinding.ActivityDataBindingListBinding; 8 9 import java.util.ArrayList;10 import java.util.List;11 12 public class DataBindingListActivity extends AppCompatActivity {13 14 @Override15 protected void onCreate(Bundle savedInstanceState) {16 super.onCreate(savedInstanceState);17 // setContentView(R.layout.activity_data_binding_list);18 ActivityDataBindingListBinding binding = DataBindingUtil.setContentView(this,R.layout.activity_data_binding_list);19 20 List list = new ArrayList<>();21 for (int i = 0; i < 100;="">) {22 User user = new User();23 user.setName('用户 ' + i );24 user.setIcon('http://qlogo1.store.qq.com/qzone/503233512/503233512/100?1311741184');25 list.add(user);26 }27 CommonAdapter adapter = new CommonAdapter<>(28 this, list, R.layout.list_item, com.example.nanchen.databindingdemo.BR.user);29 binding.setAdapter(adapter);30 31 }32 33 34 }
复制代码

 

4)大概可以运行了哈。

 

5)如何添加点击事件呢?别慌,在我们的User中加入点击方法就好了。

复制代码
1 package com.example.nanchen.databindingdemo; 2 3 import android.view.View; 4 import android.widget.Toast; 5 6 /** 7 * 继承,观察可刷新 8 * Created by 南尘 on 16-7-18. 9 */10 public class User {11 private String name;//用户名12 private String nickName;//昵称13 private String email;//邮箱14 15 private boolean vip;//是否是会员16 private int level;//级别17 private String icon;18 19 public String getIcon() {20 return icon;21 }22 23 public void setIcon(String icon) {24 this.icon = icon;25 }26 27 public int getLevel() {28 return level;29 }30 31 public void setLevel(int level) {32 this.level = level;33 }34 35 public boolean isVip() {36 return vip;37 }38 39 public void setVip(boolean vip) {40 this.vip = vip;41 }42 43 public User() {44 }45 46 public User(String name, String nickName, String email) {47 this.name = name;48 this.nickName = nickName;49 this.email = email;50 }51 52 public String getEmail() {53 return email;54 }55 56 public void setEmail(String email) {57 this.email = email;58 }59 60 public String getName() {61 return name;62 63 }64 65 public void setName(String name) {66 this.name = name;67 }68 69 public String getNickName() {70 return nickName;71 }72 73 public void setNickName(String nickName) {74 this.nickName = nickName;75 }76 77 public void clickName(View view){78 Toast.makeText(view.getContext(),'点击了用户名:' + name,Toast.LENGTH_SHORT).show();79 }80 81 public boolean longClickNickName(View view){82 Toast.makeText(view.getContext(),'长按了昵称:'+nickName,Toast.LENGTH_SHORT).show();83 return true;84 }85 86 public void click(View view){87 setName(getName() + '( 已点击 )');88 }89 }
复制代码

6)这里我们点击了用户2,什么情况?没刷新!!!!!,哦,哪里出了问题!

 

7)调皮的滑动了一下滚动条,再回去发现才刷新更改了。

9)e duo key,这里也太out了吧,说好的最屌框架呢?说好的要愉快一辈子呢?

仔细一看,才发现我们的逻辑中出了一点小问题,这样的话虽然你的list中的数据改变了,但是list并不知道,而这个adapter又没有刷新数据的方法,怎么办?

这里用到一个观察者模式,只需要把User继承BaseObservable类,并且在要更改的属性上加一个@Bindble,再在setName方法中加入这样一句话则可。

//刷新变量(变量id)
notifyPropertyChanged(com.example.nanchen.databindingdemo.BR.name);


复制代码
1 package com.example.nanchen.databindingdemo; 2 3 import android.databinding.BaseObservable; 4 import android.databinding.Bindable; 5 import android.view.View; 6 import android.widget.Toast; 7 8 /** 9 * 继承,观察可刷新10 * Created by 南尘 on 16-7-18.11 */12 public class User extends BaseObservable {13 private String name;//用户名14 private String nickName;//昵称15 private String email;//邮箱16 17 private boolean vip;//是否是会员18 private int level;//级别19 private String icon;20 21 public String getIcon() {22 return icon;23 }24 25 public void setIcon(String icon) {26 this.icon = icon;27 }28 29 public int getLevel() {30 return level;31 }32 33 public void setLevel(int level) {34 this.level = level;35 }36 37 public boolean isVip() {38 return vip;39 }40 41 public void setVip(boolean vip) {42 this.vip = vip;43 }44 45 public User() {46 }47 48 public User(String name, String nickName, String email) {49 this.name = name;50 this.nickName = nickName;51 this.email = email;52 }53 54 public String getEmail() {55 return email;56 }57 58 public void setEmail(String email) {59 this.email = email;60 }61 62 @Bindable63 public String getName() {64 return name;65 66 }67 68 public void setName(String name) {69 this.name = name;70 //刷新变量(变量id)71 notifyPropertyChanged(com.example.nanchen.databindingdemo.BR.name);72 }73 74 public String getNickName() {75 return nickName;76 }77 78 public void setNickName(String nickName) {79 this.nickName = nickName;80 }81 82 public void clickName(View view){83 Toast.makeText(view.getContext(),'点击了用户名:' + name,Toast.LENGTH_SHORT).show();84 }85 86 public boolean longClickNickName(View view){87 Toast.makeText(view.getContext(),'长按了昵称:'+nickName,Toast.LENGTH_SHORT).show();88 return true;89 }90 91 public void click(View view){92 setName(getName() + '( 已点击 )');93 }94 }
复制代码

10)再次运行:

 

现在好多了嘛,一点击就刷新了,是不是很吊?额,现在是点击整个item都可以刷新属性界面,好吧,其实无论你点击哪里,只要你加上这个click方法作为自定义属性,都可以实现这个功能,这里你要在原来的思路上实现是不是相当麻烦,而这个框架让你只需要移动一行代码的位置就可以,很高端大气上档次有木有?

这里做个示范,假如你是点击头像更改,只需要这样。

复制代码
1 2 3 layout 4 xmlns:android='http://schemas./apk/res/android' 5 xmlns:app='http://schemas./apk/res-auto'> 6 7 8 variable 9 name='user'10 type='com.example.nanchen.databindingdemo.User'/>11 12 13 LinearLayout14 android:layout_width='match_parent'15 android:layout_height='match_parent'16 android:orientation='horizontal'17 >18 19 ImageView20 android:layout_width='100dp'21 android:layout_height='100dp'22 app:imageUrl='@{user.icon}'23 android:onClick='@{ user.click }'/>24 25 TextView26 android:layout_width='match_parent'27 android:layout_height='match_parent'28 android:text='@{user.name}'29 android:gravity='center'/>30 31 32
复制代码

 

不仅可以放在这里,你还可以放在任何地方,无论是在ListView里面还是外面。

肯定这个框架还有其他的东西的,大家一起发掘咯~

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多