在第二篇文章《Android中利用Handler实现消息的分发机制(一)》中,我们讲到主线程的Looper是Android系统在启动App的时候,已经帮我们创建好了,而假设在子线程中须要去使用Handler的时候,我们就须要显式地去调用Looper的
prepare方法和loop方法,从而为子线程创建其唯一的Looper。

详细代码例如以下:

class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() { public void handleMessage(Message msg) {
Log.v("Test", "Id of LooperThread : " + Thread.currentThread().getId());
...
}
}
};
Looper.loop();
}
}

而实际上,Android SDK 中已经提供了这样一个实现,一个叫做HandlerThread 的类,它继承了线程,而且在其run方法中调用了Looper.prepare()  和 Looper.loop()  方法,从而创建了一个已经有Looper的线程,如以下代码所看到的:

    @Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}

我们在主线程中定义的Handler所相应的Looper,还是属于主线程的,那么事实上就仅仅是实现了在主线程中的异步处理而已。

而在日常开发中,当我们须要利用Handler在子线程中实现业务的处理的时候,我们就能够利用HandlerIntent来实现我们的需求。

普通情况下,我们会创建一个类,让其去继承HandlerThread,   例如以下:

   public class MyHandlerThread extends HandlerThread {
public MyHandlerThread(String name) {
super(name);
}
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.v("Test", "Id of MainThread : " + Thread.currentThread().getId());
MyHandlerThread myHandlerThread = new MyHandlerThread("MyHandlerThread");
myHandlerThread.start();
Handler handler = new Handler(myHandlerThread.getLooper(), new Callback() {
@Override
public boolean handleMessage(Message msg) {
Log.v("Test", "id of Thread by Callback : " + Thread.currentThread().getId());
return false;
}
});
handler.sendEmptyMessage(0);
}

在样例中, 创建了一个MyHandlerThead 对象,记得,它是一个线程,所以须要调用其 start 方法,让线程跑起来。

接着,就须要利用Handler当中一个构造函数Handler(Looper, Callback) ,将HandlerThread线程中的 Looper 赋给handler,而随之传入的,则是Handler.Callback的接口实现类,如上面代码所看到的。

最后调用 sendMessage方法,相应的结果例如以下:

10-28 17:24:50.438: V/Test(31694): Id of MainThread : 1
10-28 17:24:50.448: V/Test(31694): id of Thread by Callback : 91617

可见,handleMessage的处理逻辑已经在是在另外一个线程中去跑了。

普通情况下,我们在创建handlerThread的时候,也会顺便实现Handler.Callback接口,将我们要实现的代码逻辑也封装在此线程中,让代码更具有可读性,例如以下:

    public class MyHandlerThread extends HandlerThread implements Callback{
public MyHandlerThread(String name) {
super(name);
}
@Override
public boolean handleMessage(Message msg) {
Log.v("Test", "id of Thread by Callback : " + Thread.currentThread().getId());
return true;
}
} protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.v("Test", "Id of MainThread : " + Thread.currentThread().getId());
MyHandlerThread myHandlerThread = new MyHandlerThread("MyHandlerThread");
myHandlerThread.start();
Handler handler = new Handler(myHandlerThread.getLooper(), myHandlerThread);
handler.sendEmptyMessage(0); }

说到代码的可读性,有时候,我们更加看重代码之间的层次或者说模块化,耦合度等特点。

不同的业务逻辑,不同的功能,应该实如今不同的模块中,而模块与模块之间就能够通过一个消息来通信,而这样的消息通讯方式,我们就能够利用Handler和HandlerThread来实现。

比方,近期做的一个浏览器的小Demo,其类图例如以下:

在当中,我们就利用了MessageDispatcher来存放各个模块的Handler,其结构例如以下:

   private static MessageDispatcher mMsgDispatcher;  

    private SparseArray<Handler> mHandlers;
...
public void sendMessage(int target, int from, int msgWhat, Object obj){
Handler handler = mHandlers.get(target);
if(handler == null){
Logger.v("There is no Handler registered by target " + target);
return;
}
Message msg = handler.obtainMessage();
msg.what = msgWhat;
msg.obj = obj;
msg.arg1 = from;
handler.sendMessage(msg);
}; public void registerHanlder(int key, Handler handler){
mHandlers.put(key, handler);
} public void unregisterHanlder(int key){
if(mHandlers.get(key) != null){
mHandlers.delete(key);
}
} public void destroy(){
mHandlers = null;
}

在不同的模块实现中, 我们能够调用registerHandler方法,将其对象的Handler注冊到MessageDispatcher中,然后通过sendMessage方法,指定相应的目标,假设相应的目标模块也向MessageDispatcher,就能够获得其Handler,然后利用其Handler来发送消息,并由其处理。

比方,我们在BookmarkActivity中向BookmarkManager发送消息,例如以下:

mMessageDispatcher.sendMessage(MessageConstant.TARGET_BOOKMARK_MGR, MessageConstant.TARGET_BOOKMARK_ACTIVITY,
MessageConstant.MSG_BOOKMARK_GET_ALL_DIR, sparseArray);

而在BookmarkManager中,当其handler接受到相应的消息的时候,其就将会进行相应的处理,例如以下:

   class BookmarkHandlerThread extends HandlerThread implements Callback{
public BookmarkHandlerThread(String name) {
super(name);
} @SuppressWarnings("unchecked")
public boolean handleMessage(Message msg){
switch(msg.what){
case MessageConstant.MSG_BOOKMARK_GET_ALL_DIR:
//Do Something

这样,我们就行将业务逻辑和数据操作给分开了,实现了对功能编程。

尽管仅仅是一个不是非常成熟的想法,但还是希望可以跟大家分享一下,在设计代码架构的时候,可以依据功能,业务需求或者基础框架来进行分层,分块,实现代码的松耦合。

结束。

Android中利用Handler实现消息的分发机制(三)的更多相关文章

  1. 深入源代码解析Android中的Handler,Message,MessageQueue,Looper

    本文主要是对Handler和消息循环的实现原理进行源代码分析.假设不熟悉Handler能够參见博文< Android中Handler的使用>,里面对Android为何以引入Handler机 ...

  2. Android正在使用Handler实现消息分发机制(零)

    演讲前,AsyncTask文章.我们在最后谈到.AsyncTask它是利用Handler异步消息处理机制,操作结果.使用Message回到主线程,从而执行UI更新线程. 而在我们的日常开发工作,Han ...

  3. Android中的Handler机制

    直接在UI线程中开启子线程来更新TextView显示的内容,运行程序我们会发现,如下错 误:android.view.ViewRoot$CalledFromWrongThreadException: ...

  4. Android中使用Handler造成内存泄露的分析和解决

    什么是内存泄露?Java使用有向图机制,通过GC自动检查内存中的对象(什么时候检查由虚拟机决定),如果GC发现一个或一组对象为不可到达状态,则将该对象从内存中回收.也就是说,一个对象不被任何引用所指向 ...

  5. Android中使用Handler造成内存泄露

    1.什么是内存泄露? Java使用有向图机制,通过GC自动检查内存中的对象(什么时候检查由虚拟机决定),如果GC发现一个或一组对象为不可到达状态,则将该对象从内存中回收.也就是说,一个对象不被任何引用 ...

  6. Android中的Handler的机制与用法详解

    概述: 很多android初学者对android 中的handler不是很明白,其实Google参考了Windows的消息处理机制, 在Android系统中实现了一套类似的消息处理机制.在下面介绍ha ...

  7. android中的Handler和Runnable

    最近在做一个项目,在网络请求时考虑用Handler进行处理,然后就研究了一下Handler和Runnable 首先在看一下java中的Runnable The Runnable interface s ...

  8. 转:Android中的Handler的机制与用法详解

    注:Message类的用法: message的几个参数都可以携带数据,其中arg1与arg2可以携带int类型,what是用户自定义的int型,这样接受者可以了解这个消息的信息. 说明:使用Messa ...

  9. Android中的Handler,以及用Handler延迟执行

    项目中遇到一个情况,先生成文件再上传:但有时候发出指令后上传会不成功,需要再发一次指令方能上传. 猜想是由于文件还没生成就执行「上传」指令了.想到要延时.Android中单纯用currentThrea ...

随机推荐

  1. FastReport扩展类

    题记: 最近有在用FastReport进行开发报表工作,当然也有在看书,突然想到可以用书中所写来实现一个fastreport的帮助类. 对于引用第三方类库,我们都会去将这个库在调用前进行相应的封装,也 ...

  2. Redis源代码分析(二十八)--- object创建和释放redisObject物

    今天的学习更有效率.该Rio分析过,学习之间的另一种方式RedisObject文件,只想说RedisObject有些生成和转换.都是很类似的.列出里面长长的API列表: /* ------------ ...

  3. Android 建立View 圆角

    虽然很easy,不过还是录制. 混合参观 在drawable文件下 创建一个布局文件corners_bg.xml <?xml version="1.0" encoding=& ...

  4. Web层的搭建

    Web层的搭建 前言:好久没更新博客了,每天被该死的业务缠身,今天正好一个模块完成了,继续来完善我们的代码.之前的六篇完成了领域层.应用层.以及基础结构层的部分代码,这篇打算搭建下UI层的代码. DD ...

  5. Visual Studio Team Services使用教程--Readers tfs组checkin权限修改

    你也可以只开启部分代码的权限 把上面开启的整个应用的权限先去掉 只开启一个文件的权限

  6. [python]自问自答:python -m参数? (转)

    python -m xxx.py 作用是:把xxx.py文件当做模块启动但是我一直不明白当做模块启动到底有什么用.python xxx.py和python -m xxx.py有什么区别! 自问自答: ...

  7. spring中间scope详细解释

    0.思维导图 1. scope概论 spring中scope是一个很关键的概念.简单说就是对象在spring容器(IOC容器)中的生命周期,也能够理解为对象在spring容器中的创建方式. 2. sc ...

  8. eclipse 在win7 64两个图标出现位操作系统无法锁定到任务栏或任务栏

    eclipse 在win7 64位操作系统无法锁定到任务栏或者任务栏上出现两个图标 解决的方法 eclipse在win7 64bit下无法锁定到任务栏问题(或是锁定后任务栏出现两个eclipse图标) ...

  9. 学习笔记 broswerify + watchify + beefy

    broswerify “Browserify lets you require('modules') in the browser by bundling up all of your depende ...

  10. WIN8 、WIN7 下IIS7.5、IIS8 的rewrite 伪静态功能设置方法

    原文 WIN8 .WIN7 下IIS7.5.IIS8 的rewrite 伪静态功能设置方法 win7和win8系统都自带有iis的功能.关于IIS的安装,上一篇已经讲述,这里就不重复了. 下面说下在w ...