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
<?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 < 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<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)再改下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(最新)的使用(二)的更多相关文章
- Android黑科技,读取用户短信+修改系统短信数据库
安卓系统比起ios系统最大的缺点,相信大家都知道,就是系统安全问题.这篇博客就秀一波“黑科技”. 读取用户短信 Android应用能读取用户手机上的短信,相信已经不是什么新鲜事,比如我们收到的短信验证 ...
- Android基础之——startActivityForResult启动界面并返回数据,上传头像
在android应用的开发过程中,常常会出现启动一个界面后填写部分内容后带着数据返回启动前的界面,最典型的应用就是登录过程.在非常多应用程序的模块中,都有"我的"这个模块,在未登录 ...
- android黑科技系列——爆破一款应用的签名验证问题
一.前言 在之前的文章中说过Android中的安全和破解是相辅相成的,为了防止被破解,很多应用做了一些防护策略,但是防护策略也是分等级,一般简单的策略就是混淆代码和签名校验,而对于签名校验很多应用都是 ...
- android黑科技系列——微信定位聊天记录中照片的位置信息插件开发详解
一.前言 最近关于微信中,朋友之间发送原图就可能暴露你的位置信息,其实这个问题不在于微信,微信是为了更好的体验效果,才有发送原图功能,而对于拍照,发送普通图片微信后台都会过滤图片的exif信息,这样就 ...
- android黑科技系列——静态分析技术来破解Apk
一.前言 从这篇文章开始我们开始我们的破解之路,之前的几篇文章中我们是如何讲解怎么加固我们的Apk,防止被别人破解,那么现在我们要开始破解我们的Apk,针对于之前的加密方式采用相对应的破解技术,And ...
- android黑科技系列——实现静态的默认安装和卸载应用
一.访问隐藏的API方式进行静态的默认安装和卸载 1.系统安装程序 android自带了一个安装程序—/system/app/PackageInstaller.apk.大多数情况下,我们手机上安装应用 ...
- 【Android开发】完美解决Android完全退出程序
背景:假说有两个Activity, Activity1和Activity2, 1跳转到2,如果要在2退出程序,一般网上比较常见的说法是用 System.exit(0) 或是 android.os.Pr ...
- android黑科技系列——自动注入代码工具icodetools
一.前言 在前面已经介绍完了 自动给apk中注入日志代码工具icodetools原理了,在那里我们曾经说过其实离真正的可使用价值有点距离,本篇就对这个工具进行一些优化,让其真正意义上开始能工作量产.当 ...
- android黑科技系列——解析公众号文章消息和链接文章消息自动打开原理
一.辅助功能方案分析 关于WX的各种功能插件已经非常普遍了,而现在的插件都是依赖于Xposed框架进行的,所以个人觉得WX应该在这方便应对Xposed框架的使用防护,防止插件满天飞的现象,本文来介绍一 ...
随机推荐
- “.Net 社区虚拟大会”(dotnetConf) 2016 Day 3 Keynote: Scott Hanselman
美国时间 6月7日--9日,为期三天的微软.NET社区虚拟大会正式在 Channel9 上召开,美国时间6.9 是第三天, Scott Hanselman 做Keynote.今天主题围绕的是.NET ...
- AES加密
package com.edu.hpu; import java.math.BigInteger; import java.security.MessageDigest; import java.se ...
- 立即执行函数表达式(IIFE)
原文地址:benalman.com/news/2010/11/immediately-invoked-function-expression/ 译者:nzbin 也许你还没有注意到,我是一个对术语比较 ...
- jQuery.Ajax IE8 无效(CORS)
今天在开发的时候,遇到一个问题,$.get()在 IE8 浏览器不起作用,但 Chrome,Firefox 却是可以的,网上资料很多,最后发现是 IE8 默认不支持 CORS 请求,需要手动开启下: ...
- MongoDB系列(二):C#应用
前言 上一篇文章<MongoDB系列(一):简介及安装>已经介绍了MongoDB以及其在window环境下的安装,这篇文章主要讲讲如何用C#来与MongoDB进行通讯.再次强调一下,我使用 ...
- [systemtap手记]debian体系安装过程
Debian体系,本人测试用机 Ubuntu 11.10 uname -r 查看原本的内核版本为 3.0.0-12-generic 第一步: 安装systemtap包 $ sudo apt-get i ...
- iOS 委托与文本输入(内容根据iOS编程编写)
文本框(UITextField) 本章节继续编辑 JXHypnoNerd .文件地址 . 首先我们继续编辑 JXHypnosisViewController.m 修改 loadView 方法,向 ...
- MSYS2——Windows平台下模拟linux环境的搭建
最近从MSYS1.0迁移到了MSYS2.0,简单讲,MSYS2.0功能更强大,其环境模拟更加符合linux.虽然本身来自cygwin,但其集成了pacman软件管理工具,很有linux范,并且可以直接 ...
- CSS3自定义滚动条样式 -webkit-scrollbar(转)
有没有觉得浏览器自带的原始滚动条很不美观,同时也有看到很多网站的自定义滚动条显得高端,就连chrome32.0开发板都抛弃了原始的滚动条,美观多了.那webkit浏览器是如何自定义滚动条的呢? 前言 ...
- 设置Hyper-V和VMware多个服务之间共存
这个方法是解决多个服务之间不能共存,下面相当于是以Hyper-V和VMware做例子,其他的也适用. 今天准备安装VMware Workstation 10,然后玩玩MAC OS. 没想到,淡定的我双 ...