Yesterday we learned the basic usage of dataBinding together. I think you may still be stuck in it, but you don’t need to findViewById anymore. In fact, it is not the case. Today we will expand and extend to see what magic power this framework has that Google officials highly recommend. If you haven’t seen yesterday’s basic application here, you need to take a look, and attach the link: http://blog.csdn.net/cuper_/article/details/53197106
The project has been synchronized to github: https://github.com/nanchen2251/databinding
Yesterday we solved the problem of simple use and attribute transformation in xml and the use of some simple expressions in xml files. Everyone must have doubts. We will definitely use a lot of layout reuse in actual development, etc. , so is it possible to do the same in this framework? In addition, what if we want to use this framework to load images? We all know that pictures in xml can only set local pictures through src, and do not provide attributes set through url. Don't worry, the host will share this method with you.
1) First, put yesterday's xml code into a separate xml file, called user_layout.xml by the host, and set the picture here by using the app custom attribute to set the picture 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 < 3 ? 0xff03bbf9 : 0xfff60bdb }" 46 android:text="@{user.email}"/> 47 </LinearLayout> 48 </layout>
2) Then modify the xml file of the main page, activity_main.xml, since we are using left and right symmetry to display two users, so we should use list instead of the previous user, and the angle brackets used in it should be escaped. Section has already been said.
<?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<User>"/> </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) Change the code of the 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( "Liu Shilin" ); user.setNickName( "Nanchen" ); user.setEmail("[email protected]"); 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( "Chunchuner" ); user1.setNickName(null); user1.setVip(false); user1.setEmail("[email protected]"); user1.setLevel(1); // binding.setUser(user1); List<User> list = new ArrayList<>(); list.add(user); list.add(user1); binding.setUsers(list); // binding.setUser(new User("Liu Shilin","Nan Chen","[email protected]")); } }
look at the running effect
Seeing this, maybe my friends will say, cut, isn’t it just an include, this framework still doesn’t bring the feeling of flying, don’t worry, there are more powerful uses like ListView waiting for you
Let's take a look at how listView is implemented.
1) Naturally, it is necessary to define a list_item.xml first, which is used for the layout of the basic 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) Write a general adapter Adaper. Note that this is completely different from the ListView adapter you wrote in the past. We have two more attributes, one is layoutId, and the other is attribute 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 Nanchen on 16-7-18. 16 */ 17 public class CommonAdapter<T> extends BaseAdapter { 18 private Context context; // Context environment 19 private List<T> list; // General, don't know the data 20 private int layoutId; // Universal, don't know the layout 21 private int variableId; // The id of the variable 22 23 /** 24 * Construction method 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) Layout in xml, this is relatively simple, first change this to the program entry in the configuration file, and add network operation permissions, here use BR file, BR file and R file are automatically generated by the system, just R The file is used for the id of the resource. image we use a default
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>
Not only can it be placed here, you can also place it anywhere, whether it is inside or outside the ListView.
I am sure there are other things in this framework, let’s explore together~
Reposted from Nan Chen's essay