首先让我们看一个客户端图片

这是京东客户端的购物车界面。有这么一种功能,当我们在商品列表中调整商品数量等信息的时候,下方的金额总数也随之变化。

可以看出,这个界面有一个数据源,一个适配器,一个ListView。 总金额的布局是显示在ListView布局上面的。

那么怎么样可以当列表数据源变化的时候,下方的总金额(ListView 之外的UI)也变化?

有两个思路:

1、我们点击某一个列表项的某一个按钮时(可能是删除此商品按钮,可能是调整此商品数量按钮)的时候,对应执行监听事件接口回调的时候计算一下列表数据源数据得到的总金额。显示在UI中。 但是这种方法当列表项中能决定总金额的按钮比较多的时候,就会造成代码冗余。

2、给适配器设定一个观察者。当数据源发生变化的时候,观察者观察到并执计算总金额修改UI

我们这里学习第二种思路。

------------------------------------------------------------------------------------------------------------

一、首先,让我们看一下观察者模式的介绍:

观察者模式(Observer)完美的将观察者和被观察的对象分离开。举个例子,用户界面可以作为一个观察者,业务数据是被观察者,用户界面观察业务数据的变化,发现数据变化后,就显示在界面上。面向对象设计的一个原则是:系统中的每个类将重点放在某一个功能上,而不是其他方面。一个对象只做一件事情,并且将他做好。观察者模式在模块之间划定了清晰的界限,提高了应用程序的可维护性和重用性。
观察者设计模式定义了对象间的一种一对多的依赖关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新。
 
二、Adapter本身包含一个观察者模式 DataSetObserver
注意:DataSetObserver 是一个抽象类,使用的时候需要创建子类,不是接口。
Adapter可以注册多个数据观察者 registerDataSetObserver
 
三、DataSetObserver的使用
1、创建观察者对象
 private DataSetObserver sumObserver = new DataSetObserver() {
/**
* 当Adapter的notifyDataSetChanged方法执行时被调用
*/
@Override
public void onChanged() {
super.onChanged();
        //执行相应的操作
} /**
* 当Adapter 调用 notifyDataSetInvalidate方法执行时被调用
*/
@Override
public void onInvalidated() {
super.onInvalidated();
        //执行相应的操作
}
};

2、注册观察者

在onCreat()方法中

//设置Adapter的数据变化观察者,只要Adapter的notifyDataSet被调用,观察者自动调用
adapter.registerDataSetObserver(sumObserver);

3、注销观察者

在适当的位置注销观察者

比如在onDestroy()方法中注销

@Override
protected void onDestroy() {
super.onDestroy();
adapter.unregisterDataSetObserver(sumObserver);
}

四、Demo

当ListView数据源发生变化时UI发生变化。初始所有列表项都为0,点击变为2,查看总金额变化

 package com.xqx.adapterobserver;

 import android.app.Activity;
import android.database.DataSetObserver;
import android.os.Bundle;
import android.view.View;
import android.widget.*;
import org.w3c.dom.Text; import java.util.ArrayList;
import java.util.List; public class MainActivity extends Activity {
/**
* Called when the activity is first created.
*/ private ArrayAdapter<Integer> adapter ;
private List<Integer> list;
private ListView listView;
private TextView text; //创建观察者
private DataSetObserver sumObserver = new DataSetObserver() {
/**
* 当Adapter的notifyDataSetChanged方法执行时被调用
*/
@Override
public void onChanged() {
super.onChanged();
//执行相应的操作
int sum = ;
for (int i = ; i < list.size(); i++) {
sum+=list.get(i);
}
text.setText("总金额:"+sum);
} /**
* 当Adapter 调用 notifyDataSetInvalidate方法执行时被调用
*/
@Override
public void onInvalidated() {
super.onInvalidated();
//执行相应的操作
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main); list = new ArrayList<Integer>();
for (int i = ; i < ; i++) {
list.add();
}
adapter = new ArrayAdapter<Integer>(this,android.R.layout.simple_list_item_1,list);
//注册观察者
adapter.registerDataSetObserver(sumObserver);
text = (TextView) findViewById(R.id.text);
listView = (ListView) findViewById(R.id.listView);
listView.setAdapter(adapter); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
list.set(i,);
//将列表项的0变为2 更新适配器,
adapter.notifyDataSetChanged();
//执行该方法后DataSetObserver观察者观察到
}
}); } @Override
protected void onDestroy() {
super.onDestroy();
//注销观察者
adapter.unregisterDataSetObserver(sumObserver);
}
}

MainActivity.java

 <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"
> </ListView> <LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#ccc"
android:layout_gravity="bottom"
>
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="25sp"
android:textColor="#000"
android:text="总金额"
/>
</LinearLayout> </FrameLayout>

main.xml

效果图:

浅谈Adapter中观察者模式的更多相关文章

  1. 浅谈Java中的equals和==(转)

    浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str ...

  2. 浅谈Linux中的信号处理机制(二)

    首先谢谢 @小尧弟 这位朋友对我昨天夜里写的一篇<浅谈Linux中的信号处理机制(一)>的指正,之前的题目我用的“浅析”一词,给人一种要剖析内核的感觉.本人自知功力不够,尚且不能对着Lin ...

  3. 浅谈Java中的对象和引用

    浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起 ...

  4. 浅谈Java中的equals和==

    浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: String str1 = new String("hello"); String str2 = ...

  5. 转【】浅谈sql中的in与not in,exists与not exists的区别_

    浅谈sql中的in与not in,exists与not exists的区别   1.in和exists in是把外表和内表作hash连接,而exists是对外表作loop循环,每次loop循环再对内表 ...

  6. 浅谈iOS中的userAgent

    浅谈iOS中的userAgent   User-Agent(用户代理)字符串是Web浏览器用于声明自身型号版本并随HTTP请求发送给Web服务器的字符串,在Web服务器上可以获取到该字符串. 在公司产 ...

  7. 浅谈JavaScript中的闭包

    浅谈JavaScript中的闭包 在JavaScript中,闭包是指这样一个函数:它有权访问另一个函数作用域中的变量. 创建一个闭包的常用的方式:在一个函数内部创建另一个函数. 比如: functio ...

  8. 浅谈sql中的in与not in,exists与not exists的区别

    转 浅谈sql中的in与not in,exists与not exists的区别   12月12日北京OSC源创会 —— 开源技术的年终盛典 »   sql exists in 1.in和exists ...

  9. 浅谈Java中的深拷贝和浅拷贝(转载)

    浅谈Java中的深拷贝和浅拷贝(转载) 原文链接: http://blog.csdn.net/tounaobun/article/details/8491392 假如说你想复制一个简单变量.很简单: ...

随机推荐

  1. Windows 服务开发框架介绍 - Topshelf

    关于 TopShelf Topshelfis a framework for hosting services written using the .NET framework. The creati ...

  2. 正确理解静态Static关键字

    与其他语言不通,C#没有全局变量和全局函数的感念,C#的所有字段和方法都出现在一个类的上下文中,在C#中与全局字段或函数等价的就是静态字段或方法.“全局字段或方法”与“C#的静态字段或方法”没有功能上 ...

  3. windows下面go语言环境搭建

    步骤一:golang下载 下载地址是:http://www.golangtc.com/download 下载完成之后解压缩,放到你的c:/根目录下面.然后配置一下环境变量! 环境变量配置如下: 1.新 ...

  4. 左倾堆(二)之 C++的实现

    概要 上一章介绍了左倾堆的基本概念,并通过C语言实现了左倾堆.本章是左倾堆的C++实现. 目录1. 左倾堆的介绍2. 左倾堆的图文解析3. 左倾堆的C++实现(完整源码)4. 左倾堆的C++测试程序 ...

  5. 在JAVA和android中常用的单列模式

    在很多开发中,项目为了节约资源,都把一个类的构造函数变为私有化,这样整个项目中就不能创建多个实例,这样的方法我们称为单例模式 现在通过代码来简介下这个单例模式: 在新建一个java项目后,创建一个实体 ...

  6. GitHub上那些值得一试的JAVA开源库

    作为一名程序员,你几乎每天都会使用到GitHub上的那些著名Java第三方库,比如Apache Commons,Spring,Hibernate等等.除了这些,你可能还会fork或Star一些其他的开 ...

  7. 自定义能够for each的类,C#,Java,C++,C++/cli的实现方法

    自定义类能够被for each,应该算是个老生常谈的话题了,相关的资料都很多,不过这里整理总结主流语言的不同实现方式,并比较部分细节上的差异. 第一种语言,也是实现起来最简单的Java语言.在Java ...

  8. Android开发切换host应用

    由于在工作过程中常需要切换手机的host来测试不同服务器上的接口,所以想到需要这么个软件. SwitchHost在PC上是一款很好用的修改Host的软件,手机上也需要这么一款App(当然手机需要已经R ...

  9. MagicalRecord,一个简化CoreData操作的工具库

    简介 项目主页:https://github.com/magicalpanda/MagicalRecord 实例下载:https://github.com/ios122/MagicalRecord 在 ...

  10. Linux - root初始密码设置

    Ubuntu刚安装后,不能在terminal中运行su命令,因为root没有默认密码,需要手动设定. 以安装ubuntu时输入的用户名登陆,该用户在admin组中,有权限给root设定密码. 给roo ...