码迷,mamicode.com
首页 > 移动开发 > 详细

Android中的观察者模式:消息分发器(MessageDispatcher)

时间:2015-07-12 12:49:14      阅读:267      评论:0      收藏:0      [点我收藏+]

标签:

这个功能是在公司项目需求的时候写出来,本来是基础命令字模式的,但是个人喜欢对象,所有后来在一个小项目中使用时,改成了基于对象模式。

首先,是一个接口,我们称之为监听器:

  1. /**  
  2.  *   
  3.  * @author poet  
  4.  *  
  5.  */  
  6. public interface MessageObserver<T> {  
  7.   
  8.     void onMessage(T t);  
  9. }  

这里使用的是泛型,泛型<T>除了作为实际监听的对象类型,也作为监听器管理的key,届时,你将收到一个具体类型的对象。下面是关键代码:

  1. package com.poet.lib.base.data;  
  2.   
  3. import java.lang.reflect.ParameterizedType;  
  4. import java.lang.reflect.Type;  
  5. import java.util.HashMap;  
  6. import java.util.HashSet;  
  7. import java.util.Map;  
  8. import java.util.Set;  
  9.   
  10. import android.os.Handler;  
  11. import android.os.Looper;  
  12.   
  13. /** 
  14.  * 基于对象的消息分发器 
  15.  * @author poet 
  16.  * 
  17.  */  
  18. public class MessageDispatcher {  
  19.   
  20.     private static Handler sHandler;  
  21.     private static Map<Class<?>, Set<MessageObserver<?>>> sMap;  
  22.   
  23.     /** 
  24.      * 分发消息(可以在子线程调用) 
  25.      * @param t 
  26.      * @return 是否有监听器监听该消息 
  27.      */  
  28.     public static <T> boolean dispatch(final T t) {  
  29.         if (t == null) {  
  30.             throw new IllegalArgumentException("参数不可为null");  
  31.         }  
  32.         final Set<MessageObserver<?>> set;  
  33.         if (sMap == null || (set = sMap.get(t.getClass())) == null  
  34.                 || set.isEmpty()) {  
  35.             return false;  
  36.         }  
  37.         if (sHandler == null) {  
  38.             sHandler = new Handler(Looper.getMainLooper());  
  39.         }  
  40.         sHandler.post(new Runnable() {  
  41.             @Override  
  42.             public void run() {  
  43.                 synchronized (MessageDispatcher.class) {  
  44.                     for (MessageObserver<?> item : set) {  
  45.                         @SuppressWarnings("unchecked")  
  46.                         MessageObserver<T> ob = (MessageObserver<T>) item;  
  47.                         ob.onMessage(t);  
  48.                     }  
  49.                 }  
  50.             }  
  51.         });  
  52.         return true;  
  53.     }  
  54.   
  55.     public synchronized static void addObserver(MessageObserver<?> ob) {  
  56.         Class<?> clazz = checkObserver(ob);  
  57.         if (sMap == null) {  
  58.             sMap = new HashMap<Class<?>, Set<MessageObserver<?>>>();  
  59.         }  
  60.         Set<MessageObserver<?>> set = sMap.get(clazz);  
  61.         if (set == null) {  
  62.             sMap.put(clazz, set = new HashSet<MessageObserver<?>>());  
  63.         }  
  64.         set.add(ob);  
  65.     }  
  66.   
  67.     public synchronized static void removeObserver(MessageObserver<?> ob) {  
  68.         Class<?> clazz = checkObserver(ob);  
  69.         Set<MessageObserver<?>> set = sMap.get(clazz);  
  70.         if (set != null) {  
  71.             set.remove(ob);  
  72.             if (set.isEmpty()) {  
  73.                 sMap.remove(clazz);  
  74.                 set = null;  
  75.             }  
  76.         }  
  77.     }  
  78.   
  79.     private static Class<?> checkObserver(MessageObserver<?> ob) {  
  80.         Class<?> clazz;  
  81.         if (ob == null || (clazz = getGenericClass(ob)) == null) {  
  82.             throw new IllegalArgumentException("参数不可为null,或没有使用范型");  
  83.         }  
  84.         return clazz;  
  85.     }  
  86.   
  87.     private static Class<?> getGenericClass(Object obj) {  
  88.         try {  
  89.             ParameterizedType parameterizedTyped = (ParameterizedType) obj  
  90.                     .getClass().getGenericInterfaces()[0];  
  91.             Type actualType = parameterizedTyped.getActualTypeArguments()[0];  
  92.             if (actualType instanceof Class<?>) {  
  93.                 return (Class<?>) actualType;  
  94.             } else {  
  95.                 Type rawType = ((ParameterizedType) actualType).getRawType();  
  96.                 if (rawType instanceof Class<?>) {  
  97.                     return (Class<?>) rawType;  
  98.                 }  
  99.             }  
  100.         } catch (Exception e) {  
  101.             e.printStackTrace();  
  102.         }  
  103.         return null;  
  104.     }  
  105. }  


代码很明白了,就说下使用场景和扩展使用:


首先,使用MessageDispatcher前,你要确定自己要监听的对象(大多需要自己设计,不同业务要不同的对象,避免使用通用对象,造成无关的监听器收到消息),这点上,和命令字模型的设计比较,却也是不足之处。


其次,在Android中,很多人比较喜欢在Activity上实现接口,然后MessageDispatcher.addObserver(this),这时就更要注意在onDestory中调用removeObserver方法。

注意,该消息分发器,为了使得可以在子线程中调用,使用了handler,所以按照我目前的水平理解,是可以不分主线程子线程,可以直接调用的。


使用场景

1,、可以在收到服务器消息时,处理完了数据,然后通过该分发器发出消息,如果哪个Activity存在并监听了该消息对象,他将收到具体的消息对象<T>。

2、程序内部,一个界面的操作会影响到其他界面,如列表item点击进入详情,可能需要更新列表item的显示。当然这个可以在onActivityResult中处理,也可以发送广播,甚至你可以使用public static 的方法(见过一个同事这么使用,把我气的。。)。不过想来,我们这个消息分发器,倒是符合广播的部分思想:添加监听(注册广播),分发消息(发送广播)。只是我们的这个消息是完全无序的广播,并没有拦截功能,如果你们项目需要,可以给MessageObserver的onMessage方法添加返回值,并在MessageDispatcher中对MessageObserver添加优先级的管理。

3、其实在程序中,任何需要联动和沟通的地方,都可以使用这种机制。但是如果是业务比较复杂,感觉还是命令字模式比较理想,虽然我不喜欢管理命令字和根据命令字对对象进行解析转换。


最后,MessageDispatcher中getGenericClass方法使用反射,主要为了方便获取监听对象<T>的Class,这个也可以通过在MessageObserver添加一个方法由实现类提供。


不足之处,欢迎指正。

版权声明:本文为博主原创文章,未经博主允许不得转载。

Android中的观察者模式:消息分发器(MessageDispatcher)

标签:

原文地址:http://blog.csdn.net/yaakoe/article/details/46849029

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!