专栏首页Android干货浅谈Adapter中观察者模式

浅谈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 }
 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>

效果图:

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Android项目实战(二十八):Zxing二维码实现及优化

    听着music睡
  • 浅谈DrawerLayout(抽屉效果)

    听着music睡
  • Volley网络连接

    听着music睡
  • Android自定义密码输入EditTextLayout

    砸漏
  • Android 倒计时控件 CountDownView的实例代码详解

    一个精简可自定义的倒计时控件,使用 Canvas.drawArc() 绘制。实现了应用开屏页的圆环扫过的进度条效果。

    砸漏
  • Android数字选择器NumberPicker使用详解

    数字选择器NumberPicker是Android3.0之后引入的一个控件,比较常用,比如说手机常用的闹钟,可以选择小时和分钟,如果你需要兼容3.0之前版本,G...

    砸漏
  • android基于SwipeRefreshLayout实现类QQ的侧滑删除

    记得去年做一个聊天项目需要实现类似QQ的下拉刷新并且有侧滑删除的功能,在网上找了很久都没有QQ的完美,多多少少存在各种的问题,最后把下拉刷新的功能去掉后,只保留...

    砸漏
  • 从零开始搭建MVVM架构(1)——DataBinding

    从零开始搭建MVVM架构系列文章(持续更新): Android从零开始搭建MVVM架构(1)————DataBinding Android从零开始搭建M...

    蜻蜓队长
  • 自定义 behavior - 完美仿 QQ 浏览器首页,美团商家详情页

    记得两年前的时候,曾写过自定义 behavior 的文章 自定义 Behavior -仿新浪微博发现页的实现,到现在差不多有一万多的阅读量吧。

    用户2965908
  • Android开发实现自定义新闻加载页面功能实例

    本文实例讲述了Android开发实现自定义新闻加载页面功能。分享给大家供大家参考,具体如下:

    砸漏

扫码关注云+社区

领取腾讯云代金券