昨天我们一起学习了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. ASP.NET Core 中间件之压缩、缓存

    前言 今天给大家介绍一下在 ASP.NET Core 日常开发中用的比较多的两个中间件,它们都是出自于微软的 ASP.NET 团队,他们分别是 Microsoft.AspNetCore.Respons ...

  2. 为C# as 类型转换及Assembly.LoadFrom埋坑!

    背景: 不久前,我发布了一个调试工具:发布:.NET开发人员必备的可视化调试工具(你值的拥有) 效果是这样的: 之后,有小部分用户反映,工具用不了(没反应或有异常)~~~ 然后,建议小部分用户换个电脑 ...

  3. .net core快速上手

    2014年11月12日的Connect ();开发者活动上宣布将.NET堆栈基于MIT协议开源,并且提供开源保证,托管在Github上.当时的版本与最终目标相距甚远,然而有一点可以肯定的是,这是一个与 ...

  4. Mediaplayer error (-19,0)

    Android MediaPlayer 发生 error (-19,0) 错误解决方法. 引起原因:由于多次实例化MediaPlayer.start() 进行播放操作引起的.由于没有及时释放内存资源导 ...

  5. git 命令

    切换仓库地址: git remote set-url origin xxx.git切换分支:git checkout name撤销修改:git checkout -- file删除文件:git rm  ...

  6. JdbcTemplate+PageImpl实现多表分页查询

    一.基础实体 @MappedSuperclass public abstract class AbsIdEntity implements Serializable { private static ...

  7. H5项目开发分享——用Canvas合成文字

    以前曾用Canvas合成.裁剪.图片等<用H5中的Canvas等技术制作海报>.这次用Canvas来画文字. 下图中"老王考到驾照后"这几个字是画在Canvas上的,与 ...

  8. 【干货分享】流程DEMO-事务呈批表

    流程名: 事务呈批表  业务描述: 办公采购.会议费用等事务的申请.流程发起时,会检查预算,如果预算不够,将不允许发起费用申请,如果预算够用,将发起流程,同时占用相应金额的预算,但撤销流程会释放相应金 ...

  9. 品牌营销:不要Beat,要逼格!

             品牌营销:不要Beat,要逼格! 奥美的创始人大卫·奥格威说,广告营销应当是"具有风度的推销产品".而当下的营销手段,"风度"早已被抛之脑后, ...

  10. 为什么你SQL Server的数据库文件的Date modified没有变化呢?

    在SQL Server数据库中,数据文件与事务日志文件的修改日期(Date Modified)是会变化的,但是有时候你会发现你的数据文件或日志文件的修改日期(Date Modified)几个月甚至是半 ...