Adapter中观察者模式的应用

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

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

可以看出,这个界面有一个数据源,一个适配器,一个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,查看总金额变化

 1 package com.xqx.adapterobserver;
 2
 3 import android.app.Activity;
 4 import android.database.DataSetObserver;
 5 import android.os.Bundle;
 6 import android.view.View;
 7 import android.widget.*;
 8 import org.w3c.dom.Text;
 9
10 import java.util.ArrayList;
11 import java.util.List;
12
13 public class MainActivity extends Activity {
14     /**
15      * Called when the activity is first created.
16      */
17
18     private ArrayAdapter<Integer> adapter ;
19     private List<Integer> list;
20     private ListView listView;
21     private TextView text;
22
23     //创建观察者
24     private DataSetObserver sumObserver = new DataSetObserver() {
25         /**
26          * 当Adapter的notifyDataSetChanged方法执行时被调用
27          */
28         @Override
29         public void onChanged() {
30             super.onChanged();
31             //执行相应的操作
32             int sum = 0;
33             for (int i = 0; i < list.size(); i++) {
34                 sum+=list.get(i);
35             }
36             text.setText("总金额:"+sum);
37         }
38
39         /**
40          * 当Adapter 调用 notifyDataSetInvalidate方法执行时被调用
41          */
42         @Override
43         public void onInvalidated() {
44             super.onInvalidated();
45             //执行相应的操作
46         }
47     };
48     @Override
49     public void onCreate(Bundle savedInstanceState) {
50         super.onCreate(savedInstanceState);
51         setContentView(R.layout.main);
52
53         list = new ArrayList<Integer>();
54         for (int i = 0; i < 30; i++) {
55             list.add(0);
56         }
57         adapter = new ArrayAdapter<Integer>(this,android.R.layout.simple_list_item_1,list);
58         //注册观察者
59         adapter.registerDataSetObserver(sumObserver);
60         text = (TextView) findViewById(R.id.text);
61         listView = (ListView) findViewById(R.id.listView);
62         listView.setAdapter(adapter);
63
64         listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
65             @Override
66             public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
67                 list.set(i,2);
68                 //将列表项的0变为2 更新适配器,
69                 adapter.notifyDataSetChanged();
70                 //执行该方法后DataSetObserver观察者观察到
71             }
72         });
73
74     }
75
76     @Override
77     protected void onDestroy() {
78         super.onDestroy();
79         //注销观察者
80         adapter.unregisterDataSetObserver(sumObserver);
81     }
82 }

MainActivity.java

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3               android:orientation="vertical"
 4               android:layout_width="fill_parent"
 5               android:layout_height="fill_parent"
 6         >
 7         <ListView
 8                 android:id="@+id/listView"
 9                 android:layout_width="match_parent"
10                 android:layout_height="match_parent"
11                 >
12
13         </ListView>
14
15         <LinearLayout
16                 android:layout_width="match_parent"
17                 android:layout_height="50dp"
18                 android:background="#ccc"
19                 android:layout_gravity="bottom"
20                 >
21             <TextView
22                     android:id="@+id/text"
23                     android:layout_width="wrap_content"
24                     android:layout_height="wrap_content"
25                     android:textSize="25sp"
26                     android:textColor="#000"
27                     android:text="总金额"
28                     />
29         </LinearLayout>
30
31 </FrameLayout>

main.xml

效果图:

时间: 2024-08-03 22:59:28

Adapter中观察者模式的应用的相关文章

ViewPager的Adapter中视图重用

ViewPager的PagerAdapter不像ListView/GridView的BaseAdapter,它是没有内部视图重用机制的,也就是说我先inflate出来一个,然后调用destroyItem后,这个视图就被抛弃了,如果需要更多的视图,则需要再次inflate.如果ViewPager中的所有视图基本相同,就存在内存的浪费了.这里使用一个非常简单的方法实现视图的重用: List<View> mViewList = new ArrayList<View>(); public

自定义Adapter中实现startActivityForResult的分析

最近几天在做文件上传的时候,想在自定义Adapter中启动activity时也返回Intent数据,于是想到了用startActivityForResult,可是用mContext怎么也调不出这个方法,只能调用startActivity这个方法,于是在网上搜一下,可以利用一个方式可以间接的解决这个问题,果断贴代码: Intent mIntent = new Intent(mContext,clazz);((Activity) mContext).startActivityForResult(mI

java中观察者模式Observable和Observer

25.java中观察者模式Observable和Observer 如果想要实现观察者模式,则必须依靠java.util包中提供的Observable类和Observer接口 观察者设计模式 现在很多的购房者都在关注着房子的价格变化,每当房子价格变化的时候,所有的购房者都可以观察得到. 实际上以上的购房者就是观察者,他们所关注的房价就是被观察者 其中要求,被观察者需要继承Observable类,观察则需要实现Observer接口 具体实现如下 房价的实现 1 class House extends

在Adapter中使用Holder的那些坑

??在使用GridView.ListView时,通常会在Adapter中采用Holder缓存每一项以提高效率,但如果没有用好Holder,这个缓存机制会导致许多意想不到的问题,结合自己的经验特地总结一下,以免今后再犯. 内容错乱 ??在Adapter的getView方法中通过position更新每一项的内容,对于根据判断条件给每一项设置属性的情况,每个判断条件下都需要给每一项的每个属性赋值,否则在滑动ListView或GridView时会导致内容错乱,比如下面这段代码是在getView中调用的一

Android中观察者模式的升入理解

以前对Java中的观察者模式只知道一点皮毛,在接触Android的过程中,逐渐认识到观察者模式是如此的重要,android中许多地方都用到了观察者模式例如ContentResolver操作,来总结一下android中观察者模式的使用技巧 我所理解的观察者模式是这样子的:: 以一个例子来说明: 在service中有一个int类型的数据i,我在service中启动一个定时器去不断更新这个值,当我在activity中启动这个服务一次之后,每当i变化的时候我的activity要自动的同步更新这个值来显示

js中观察者模式的应用

实际的移动端引用backbone框架过于庞大,最近代码重构,为了实现MVC的基本功能而写了一个小型的框架,其中比较核心的内容,大概就是事件的注册触发机制,大致的实现就应用到了设计模式中观察者模式. ObserverPattern模型 上图大概是观察者模式的基本构成,目标Subject,维护基本属性observers,可以添加和删除观察者,观察者Observer,里面有方法update,而目标Subject的notify方法则需要遍历自身observers属性每个成员,并执行它的update方法.

android viewpager change adapter ---在使用viewpager设置新的adapter的时候发现页面还是显示旧的adapter中的值

有一个需求是当用户选择navigationview中的某一项时,右边的viewpager需要动态切换不同的adapter 发现直接setAdapter没有任何反应,加载的数据还是旧的数据 折腾了半天只需要将 FragmentPagerAdapter 换成 FragmentStatePagerAdapter就好了具体百度两者区别,有时间我写个总结出来大概的理解: FragmentPagerAdapter会缓存多个数据,适合viewpager中的数据不会经常变化 FragmentStatePager

java中观察者模式的使用场景

观察者模式 是一种非常经典 非常常用的设计模式. 一个对象的行为 依赖于 另一个对象的状态.或者换一种说法,当被观察对象(目标对象)的状态发生改变时 ,会直接影响到观察对象的行为. 特点一 : 被观察者 和观察者 一般是 一对多的关系,一个被观察者 对应多个观察者,当一个被观察者的状态发生改变时,被观察者通知观察者, 然后可以在观察者内部 进行业务逻辑的处理. JDK 提供了 一套 观察者模式的实现,在java.util包中, java.util.Observable类和java.util.Ob

项目中观察者模式的应用

目前项目中最多用的模式就是观察者模式了...该模式是当有数据状态变化需要及时通知的时候使用的 项目中其中之一的应用场景: 当网络状态发生变化时影视下载界面提示当前是使用免费的wifi还是机主自己的流量 1.首先定义被观察者的实体类 public class NetworkTypeNotifier extends Observable { //发生变化时调用该方法通知 public void notifyAll(NetworkType networkType) { this.setChanged(