zoukankan      html  css  js  c++  java
  • android黑科技——完美解决界面逻辑的数据框架DataBinding(最新)的使用(二)

    昨天我们一起学习了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 <?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里面还是外面。

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

  • 相关阅读:
    Linux之文档与目录结构
    Linux介绍
    CentOS7下zip解压和unzip压缩文件
    yum 命令讲解
    Linux安装redis
    pip更新问题
    第一章-KS8初体验 安装部署
    MVC Razor视图引擎
    MVC 组件之间的关系
    Web应用程序和网站的区别
  • 原文地址:https://www.cnblogs.com/liushilin/p/5683721.html
Copyright © 2011-2022 走看看