昨天我们一起学习了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

 <?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="user"
type="com.example.nanchen.databindingdemo.User">
</variable>
</data> <LinearLayout
android:layout_width="0dp"
android:layout_weight = "1"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
tools:context="com.example.nanchen.databindingdemo.MainActivity"> <ImageView
android:layout_width="100dp"
android:layout_height="100dp"
app:imageUrl="@{ user.icon }"/> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="25sp"
android:onClick="@{user.clickName}"
android:textColor="@{user.vip? 0xffff0000:0xff000000}"
android:text="@{user.nickName + `(` + user.name +`)`}"/> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="25sp"
android:onLongClick="@{user.longClickNickName}"
android:text="@{user.nickName ?? user.name}"/> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="25sp"
android:textColor="@{user.level &lt; 3 ? 0xff03bbf9 : 0xfff60bdb }"
android:text="@{user.email}"/>
</LinearLayout>
</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的布局。

 <?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"> <data>
<variable
name="user"
type="com.example.nanchen.databindingdemo.User"/>
</data> <LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:onClick="@{ user.click }"> <ImageView
android:layout_width="100dp"
android:layout_height="100dp"
app:imageUrl="@{user.icon}"/> <TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@{user.name}"
android:gravity="center"/> </LinearLayout>
</layout>

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

 package com.example.nanchen.databindingdemo;

 import android.content.Context;
import android.databinding.DataBindingUtil;
import android.databinding.ViewDataBinding;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter; import java.util.List; /**
* ListView的通用Adapter
* Created by 南尘 on 16-7-18.
*/
public class CommonAdapter<T> extends BaseAdapter {
private Context context;//上下文环境
private List<T> list;//通用的,不知道数据
private int layoutId;//通用的,不知道布局
private int variableId;//变量的id /**
* 构造方法
*/
public CommonAdapter(Context context, List<T> list, int layoutId, int variableId) {
this.context = context;
this.list = list;
this.layoutId = layoutId;
this.variableId = variableId;
} @Override
public int getCount() {
if (list!=null)
return list.size();
return 0;
} @Override
public Object getItem(int position) {
return list.get(position);
} @Override
public long getItemId(int position) {
return position;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewDataBinding binding = null;
if (convertView == null){
binding = DataBindingUtil.inflate(LayoutInflater.from(context),layoutId,parent,false);
}else{
binding = DataBindingUtil.getBinding(convertView);
}
binding.setVariable(variableId,list.get(position));
return binding.getRoot();
}
}

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

 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.ActivityDataBindingListBinding; import java.util.ArrayList;
import java.util.List; public class DataBindingListActivity extends AppCompatActivity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_data_binding_list);
ActivityDataBindingListBinding binding = DataBindingUtil.setContentView(this,R.layout.activity_data_binding_list); List<User> list = new ArrayList<>();
for (int i = 0; i < 100; i++) {
User user = new User();
user.setName("用户 " + i );
user.setIcon("http://qlogo1.store.qq.com/qzone/503233512/503233512/100?1311741184");
list.add(user);
}
CommonAdapter<User> adapter = new CommonAdapter<>(
this, list, R.layout.list_item, com.example.nanchen.databindingdemo.BR.user);
binding.setAdapter(adapter); } }

4)大概可以运行了哈。

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

 package com.example.nanchen.databindingdemo;

 import android.view.View;
import android.widget.Toast; /**
* 继承,观察可刷新
* Created by 南尘 on 16-7-18.
*/
public class User {
private String name;//用户名
private String nickName;//昵称
private String email;//邮箱 private boolean vip;//是否是会员
private int level;//级别
private String icon; public String getIcon() {
return icon;
} public void setIcon(String icon) {
this.icon = icon;
} public int getLevel() {
return level;
} public void setLevel(int level) {
this.level = level;
} public boolean isVip() {
return vip;
} public void setVip(boolean vip) {
this.vip = vip;
} public User() {
} public User(String name, String nickName, String email) {
this.name = name;
this.nickName = nickName;
this.email = email;
} public String getEmail() {
return email;
} public void setEmail(String email) {
this.email = email;
} public String getName() {
return name; } public void setName(String name) {
this.name = name;
} public String getNickName() {
return nickName;
} public void setNickName(String nickName) {
this.nickName = nickName;
} public void clickName(View view){
Toast.makeText(view.getContext(),"点击了用户名:" + name,Toast.LENGTH_SHORT).show();
} public boolean longClickNickName(View view){
Toast.makeText(view.getContext(),"长按了昵称:"+nickName,Toast.LENGTH_SHORT).show();
return true;
} public void click(View view){
setName(getName() + "( 已点击 )");
}
}

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

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

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

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

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

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

 import android.databinding.BaseObservable;
import android.databinding.Bindable;
import android.view.View;
import android.widget.Toast; /**
* 继承,观察可刷新
* Created by 南尘 on 16-7-18.
*/
public class User extends BaseObservable {
private String name;//用户名
private String nickName;//昵称
private String email;//邮箱 private boolean vip;//是否是会员
private int level;//级别
private String icon; public String getIcon() {
return icon;
} public void setIcon(String icon) {
this.icon = icon;
} public int getLevel() {
return level;
} public void setLevel(int level) {
this.level = level;
} public boolean isVip() {
return vip;
} public void setVip(boolean vip) {
this.vip = vip;
} public User() {
} public User(String name, String nickName, String email) {
this.name = name;
this.nickName = nickName;
this.email = email;
} public String getEmail() {
return email;
} public void setEmail(String email) {
this.email = email;
} @Bindable
public String getName() {
return name; } public void setName(String name) {
this.name = name;
//刷新变量(变量id)
notifyPropertyChanged(com.example.nanchen.databindingdemo.BR.name);
} public String getNickName() {
return nickName;
} public void setNickName(String nickName) {
this.nickName = nickName;
} public void clickName(View view){
Toast.makeText(view.getContext(),"点击了用户名:" + name,Toast.LENGTH_SHORT).show();
} public boolean longClickNickName(View view){
Toast.makeText(view.getContext(),"长按了昵称:"+nickName,Toast.LENGTH_SHORT).show();
return true;
} public void click(View view){
setName(getName() + "( 已点击 )");
}
}

10)再次运行:

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

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

 <?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"> <data>
<variable
name="user"
type="com.example.nanchen.databindingdemo.User"/>
</data> <LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
> <ImageView
android:layout_width="100dp"
android:layout_height="100dp"
app:imageUrl="@{user.icon}"
android:onClick="@{ user.click }"/> <TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@{user.name}"
android:gravity="center"/> </LinearLayout>
</layout>

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

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

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

  1. Android黑科技,读取用户短信+修改系统短信数据库

    安卓系统比起ios系统最大的缺点,相信大家都知道,就是系统安全问题.这篇博客就秀一波“黑科技”. 读取用户短信 Android应用能读取用户手机上的短信,相信已经不是什么新鲜事,比如我们收到的短信验证 ...

  2. Android基础之——startActivityForResult启动界面并返回数据,上传头像

    在android应用的开发过程中,常常会出现启动一个界面后填写部分内容后带着数据返回启动前的界面,最典型的应用就是登录过程.在非常多应用程序的模块中,都有"我的"这个模块,在未登录 ...

  3. android黑科技系列——爆破一款应用的签名验证问题

    一.前言 在之前的文章中说过Android中的安全和破解是相辅相成的,为了防止被破解,很多应用做了一些防护策略,但是防护策略也是分等级,一般简单的策略就是混淆代码和签名校验,而对于签名校验很多应用都是 ...

  4. android黑科技系列——微信定位聊天记录中照片的位置信息插件开发详解

    一.前言 最近关于微信中,朋友之间发送原图就可能暴露你的位置信息,其实这个问题不在于微信,微信是为了更好的体验效果,才有发送原图功能,而对于拍照,发送普通图片微信后台都会过滤图片的exif信息,这样就 ...

  5. android黑科技系列——静态分析技术来破解Apk

    一.前言 从这篇文章开始我们开始我们的破解之路,之前的几篇文章中我们是如何讲解怎么加固我们的Apk,防止被别人破解,那么现在我们要开始破解我们的Apk,针对于之前的加密方式采用相对应的破解技术,And ...

  6. android黑科技系列——实现静态的默认安装和卸载应用

    一.访问隐藏的API方式进行静态的默认安装和卸载 1.系统安装程序 android自带了一个安装程序—/system/app/PackageInstaller.apk.大多数情况下,我们手机上安装应用 ...

  7. 【Android开发】完美解决Android完全退出程序

    背景:假说有两个Activity, Activity1和Activity2, 1跳转到2,如果要在2退出程序,一般网上比较常见的说法是用 System.exit(0) 或是 android.os.Pr ...

  8. android黑科技系列——自动注入代码工具icodetools

    一.前言 在前面已经介绍完了 自动给apk中注入日志代码工具icodetools原理了,在那里我们曾经说过其实离真正的可使用价值有点距离,本篇就对这个工具进行一些优化,让其真正意义上开始能工作量产.当 ...

  9. android黑科技系列——解析公众号文章消息和链接文章消息自动打开原理

    一.辅助功能方案分析 关于WX的各种功能插件已经非常普遍了,而现在的插件都是依赖于Xposed框架进行的,所以个人觉得WX应该在这方便应对Xposed框架的使用防护,防止插件满天飞的现象,本文来介绍一 ...

随机推荐

  1. 领域驱动和MVVM应用于UWP开发的一些思考

    领域驱动和MVVM应用于UWP开发的一些思考 0x00 起因 有段时间没写博客了,其实最近本来是根据梳理的MSDN上的资料(UWP开发目录整理)有条不紊的进行UWP学习的.学习中有了心得体会或遇到了问 ...

  2. Cassandra简介

    在前面的一篇文章<图形数据库Neo4J简介>中,我们介绍了一种非常流行的图形数据库Neo4J的使用方法.而在本文中,我们将对另外一种类型的NoSQL数据库——Cassandra进行简单地介 ...

  3. 如何正确使用日志Log

    title: 如何正确使用日志Log date: 2015-01-08 12:54:46 categories: [Python] tags: [Python,log] --- 文章首发地址:http ...

  4. 深究标准IO的缓存

    前言 在最近看了APUE的标准IO部分之后感觉对标准IO的缓存太模糊,没有搞明白,APUE中关于缓存的部分一笔带过,没有深究缓存的实现原理,这样一本被吹上天的书为什么不讲透彻呢?今天早上爬起来赶紧找了 ...

  5. zookeeper源码分析之六session机制

    zookeeper中session意味着一个物理连接,客户端连接服务器成功之后,会发送一个连接型请求,此时就会有session 产生. session由sessionTracker产生的,sessio ...

  6. java单向加密算法小结(2)--MD5哈希算法

    上一篇文章整理了Base64算法的相关知识,严格来说,Base64只能算是一种编码方式而非加密算法,这一篇要说的MD5,其实也不算是加密算法,而是一种哈希算法,即将目标文本转化为固定长度,不可逆的字符 ...

  7. 虚拟机VMware12.05下安装Ubuntu16.04几个关键地方

    在踩了自己按照网上的教程安装Ubuntu之后,仍然踩了不少坑,鼓捣了一段时间,才达到自己想要的界面.   下面就来说说,大家可能也会遇到的情况:   1.安装ISO镜像时候,路径直接选择 你从Ubun ...

  8. github入门到上传本地项目【网上资源整合】

    [在原文章的基础上,修改了描述的不够详细的地方,对内容进行了扩充,整合了网上的一些资料] [内容主要来自http://www.cnblogs.com/specter45/p/github.html#g ...

  9. angularJS(5)

    angularJS(5) 一,数据循环:特别要注意作用域 使用ng-repeat指令. <div ng-app="myApp" ng-controller="myC ...

  10. BZOJ3198[SDOI2013]SPRING

    Description Input Output Sample Input 3 3 1 2 3 4 5 6 1 2 3 0 0 0 0 0 0 4 5 6 Sample Output 2 HINT 题 ...