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框架的使用防护,防止插件满天飞的现象,本文来介绍一 ...
随机推荐
- Elasticsearch 5.0 中term 查询和match 查询的认识
Elasticsearch 5.0 关于term query和match query的认识 一.基本情况 前言:term query和match query牵扯的东西比较多,例如分词器.mapping ...
- 奇异值分解(SVD)原理与在降维中的应用
奇异值分解(Singular Value Decomposition,以下简称SVD)是在机器学习领域广泛应用的算法,它不光可以用于降维算法中的特征分解,还可以用于推荐系统,以及自然语言处理等领域.是 ...
- TechEmpower 13轮测试中的ASP.NET Core性能测试
应用性能直接影响到托管服务的成本,因此公司在开发应用时需要格外注意应用所使用的Web框架,初创公司尤其如此.此外,糟糕的应用性能也会影响到用户体验,甚至会因此受到相关搜索引擎的降级处罚.在选择框架时, ...
- setTimeout 的黑魔法
setTimeout,前端工程师必定会打交道的一个函数.它看上去非常的简单,朴实.有着一个很不平凡的名字--定时器.让年少的我天真的以为自己可以操纵未来.却不知朴实之中隐含着惊天大密.我还记得我第一次 ...
- react-redux
1. 首先redux,与react是两个独立的个体,项目中可以只用react,也可以只用redux 1.1 react-redux: 是一个redux作者专门为react制作的 redux, 增加了新 ...
- mysql进阶之存储过程
往往看别人的代码会有这样的感慨: 看不懂 理还乱 是离愁 别是一番滋味在心头 为什么要使用存储过程? 在mysql开发中使用存储过程的理由: 当希望在不同的应用程序或平台上执行相同的函数,或者封装特定 ...
- 移动BPM解决方案分享
畅通开放 无边界的渠道 效率倍增 更高效的处理方式 即时共享 更强大的决策能力 各种终端应用 帮您实现:新任务通知.任务预警.催办.任务审批.任何数据汇总提醒消息通知...... 短信 客户端: ...
- TCP/IP之Nagle算法与40ms延迟
Nagle算法是针对网络上存在的微小分组可能会在广域网上造成拥塞而设计的.该算法要求一个TCP连接上最多只能有一个未被确认的未完成的小分组,在该分组确认到达之前不能发送其他的小分组.同时,TCP收集这 ...
- linux 如何对文件解压或打包压缩
tar命令用与对文件打包压缩或解压,格式: tar [选项] [文件] 打包并压缩文件: tar -czvf 压缩包名 .tar.gz 解压并展开压缩包: tar -xzvf 压缩包名 .tar. ...
- jQuery.data() 使用方法
data() 方法向被选元素附加数据,或者从被选元素获取数据.在实际开发中,可以用来记录上一步操作某一对象的值,来给下一步操作做一些判断 $("#btn1").click(func ...