My Android growth path (9) - black technology dataBinding (2)

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

copy code
 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>
copy code

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.

copy code
<?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>
copy code

 

3) Change the code of the Activity

copy code
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]")); 
    }
}
copy code

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.

copy code
 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>
copy code

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

copy code
 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 }
copy code

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

copy code
 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 }
copy code

 

4)大概可以运行了哈。

 

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

copy code
 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 }
copy code

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

 

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

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

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

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

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


copy code
 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 }
copy code

10)再次运行:

 

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

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

copy code
 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>
copy code

 

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

Guess you like

Origin blog.csdn.net/cuper_/article/details/53197312