我的Android成长之路(9)----黑科技dataBinding(二)


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

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

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

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

复制代码
 1 <?xml version="1.0" encoding="utf-8"?>
2 <layout
3 xmlns:android="http://schemas.android.com/apk/res/android"
4 xmlns:tools="http://schemas.android.com/tools"
5 xmlns:app="http://schemas.android.com/apk/res-auto">
6 <data>
7 <variable
8 name="user"
9 type="com.example.nanchen.databindingdemo.User">
10 </variable>
11 </data>
12
13 <LinearLayout
14 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 <ImageView
22 android:layout_width="100dp"
23 android:layout_height="100dp"
24 app:imageUrl="@{ user.icon }"/>
25
26 <TextView
27 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 <TextView
35 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 <TextView
42 android:layout_width="wrap_content"
43 android:layout_height="wrap_content"
44 android:textSize="25sp"
45 android:textColor="@{user.level &lt; 3 ? 0xff03bbf9 : 0xfff60bdb }"
46 android:text="@{user.email}"/>
47 </LinearLayout>
48 </layout>
复制代码

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

复制代码
<?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"
xmlns:tools
="http://schemas.android.com/tools">

<data>

<!--<variable-->
<!--name="user"-->
<!--type="com.example.nanchen.databindingdemo.User">-->
<!--</variable>-->

<import type="com.example.nanchen.databindingdemo.User"/>
<variable
name
="users"
type
="java.util.List&lt;User&gt;"/>
</data>

<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] }"/>
</LinearLayout>
</layout>
复制代码

 

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
<User> 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 <?xml version="1.0" encoding="utf-8"?>
2
3 <layout
4 xmlns:android="http://schemas.android.com/apk/res/android"
5 xmlns:app="http://schemas.android.com/apk/res-auto">
6
7 <data>
8 <variable
9 name="user"
10 type="com.example.nanchen.databindingdemo.User"/>
11 </data>
12
13 <LinearLayout
14 android:layout_width="match_parent"
15 android:layout_height="match_parent"
16 android:orientation="horizontal"
17 android:onClick="@{ user.click }">
18
19 <ImageView
20 android:layout_width="100dp"
21 android:layout_height="100dp"
22 app:imageUrl="@{user.icon}"/>
23
24 <TextView
25 android:layout_width="match_parent"
26 android:layout_height="match_parent"
27 android:text="@{user.name}"
28 android:gravity="center"/>
29
30 </LinearLayout>
31 </layout>
复制代码

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的通用Adapter
15 * Created by 南尘 on 16-7-18.
16 */
17 public class CommonAdapter<T> extends BaseAdapter {
18 private Context context;//上下文环境
19 private List<T> list;//通用的,不知道数据
20 private int layoutId;//通用的,不知道布局
21 private int variableId;//变量的id
22
23 /**
24 * 构造方法
25 */
26 public CommonAdapter(Context context, List<T> list, int layoutId, int variableId) {
27 this.context = context;
28 this.list = list;
29 this.layoutId = layoutId;
30 this.variableId = variableId;
31 }
32
33 @Override
34 public int getCount() {
35 if (list!=null)
36 return list.size();
37 return 0;
38 }
39
40 @Override
41 public Object getItem(int position) {
42 return list.get(position);
43 }
44
45 @Override
46 public long getItemId(int position) {
47 return position;
48 }
49
50 @Override
51 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 @Override
15 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<User> list = new ArrayList<>();
21 for (int i = 0; i < 100; i++) {
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<User> 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 @Bindable
63 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 <?xml version="1.0" encoding="utf-8"?>
2
3 <layout
4 xmlns:android="http://schemas.android.com/apk/res/android"
5 xmlns:app="http://schemas.android.com/apk/res-auto">
6
7 <data>
8 <variable
9 name="user"
10 type="com.example.nanchen.databindingdemo.User"/>
11 </data>
12
13 <LinearLayout
14 android:layout_width="match_parent"
15 android:layout_height="match_parent"
16 android:orientation="horizontal"
17 >
18
19 <ImageView
20 android:layout_width="100dp"
21 android:layout_height="100dp"
22 app:imageUrl="@{user.icon}"
23 android:onClick="@{ user.click }"/>
24
25 <TextView
26 android:layout_width="match_parent"
27 android:layout_height="match_parent"
28 android:text="@{user.name}"
29 android:gravity="center"/>
30
31 </LinearLayout>
32 </layout>
复制代码

 

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

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

转自南尘随笔

智能推荐

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
© 2014-2019 ITdaan.com 粤ICP备14056181号  

赞助商广告