Android开发基础Android之handler

Handler的定义
handler 是为了实现 异步而生的
Android是消息启动的,UI线程是一个Looper线程 , Looper中维护这一个MessageQueue , UI线程将不断处理这些消息 以完成UI的更新等异步操作
handler扮演了往已经Looper线程的message queue上添加消息和处理消息的角色(只处理由自己发出的消息),即 通知MQ它要执行一个任务(sendMessage),并在loop到自己的时候执行该任务(handleMessage),整个过程是异步的。

案例解析:
当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的UI控件,比如说, 你要是点击一个 Button ,Android会分发事件到Button上,来响应你的操作。 但是如果此时需要一个耗时的操作,例如: 联网读取数据, 如果你放在主线程中的话,界面会出现假死现象, 因为在处理你的耗时操作 如果这个操作超过5s就会anr
所以耗时操作应该放在一个子线程中, 但这样子线程就会涉及到UI更新,Android主线程是线程不安全的,(更新UI只能在主线程中更新,子线程中不能更新UI)
那么子线程就需要通知主线程来更新数据,于是 就可以使用Handler. 如果Handler对象在主线程中被创建,那这个Handler就运行在主线程中(UI线程中),  在子线程中可以 用这个handler发送消息 然后这个handler就把这个消息放到主线程的mq中 然后UI线程就能可以 进行更新等操作了:
具体如下图:
1365065802_5494.png
2013-5-20 09:56 上传
下载附件 (35.77 KB)

Handler实现原理
分两个方面来讲
1.发送消息:
?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 此方法用于向对应的Looper的MQ上发送Runnable对象,它的run方法将在handler对应的Looper线程中执行
    public final boolean post(Runnable r)
    {
    
       return  sendMessageDelayed(getPostMessage(r), 0 );  // getPostMessage(r)将runnable封装成message
    }
    private final Message getPostMessage(Runnable r) {
        Message m = Message.obtain();  //message工厂
        m.callback = r;  //将runnable设为message的callback,
        return m;
    }
    public boolean sendMessageAtTime(Message msg, long uptimeMillis)
    {
        boolean sent = false ;
        MessageQueue queue = mQueue;
        if (queue != null ) {
            msg.target = this // message的target必须设为该handler
            sent = queue.enqueueMessage(msg, uptimeMillis);
        }
        else {
            RuntimeException e = new RuntimeException(
                this + " sendMessageAtTime() called with no mQueue" );
            Log.w( "Looper" , e.getMessage(), e);
        }
        return sent;
    }


通过handler发出的message有如下特点:
1.message.target为该handler对象,这确保了looper执行到该message时能找到处理它的handler,即loop()方法中的关键代码
msg.target.dispatchMessage(msg);
2.post发出的message,其callback为Runnable对象

Handler处理消息
消息的处理是通过核心方法dispatchMessage(Message msg)与handleMessage(Message msg)完成的
?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
View Code
    // 处理消息,该方法由looper调用
    public void dispatchMessage(Message msg) {
        if (msg.callback != null ) {
            // 如果message设置了callback,即runnable消息,处理callback
            handleCallback(msg);
        } else {
            // 如果handler本身设置了callback,则执行callback
            if (mCallback != null ) {
                 /* 这种方法允许让activity等来实现Handler.Callback接口,避免了自己编写handler重写handleMessage方法。
                if (mCallback.handleMessage(msg)) {
                    return ;
                }
            }
            // 如果message没有callback,则调用handler的钩子方法handleMessage
            handleMessage(msg);
        }
    }
   
    // 处理runnable消息
    private final void handleCallback(Message message) {
        message.callback.run();  //直接调用run方法!
    }
    // 由子类实现的钩子方法
    public void handleMessage(Message msg) {
    }

方法由开发者实现外(实现具体逻辑),handler的内部工作机制对开发者是透明的。这正是handler API设计的精妙之处


Handler的使用
1.最基本的使用  以获取sina的html为例
首先是让Thread发送消息:
?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
new Thread() { 
            public void run() { 
                Message msg = myHandler.obtainMessage(); 
                try
                    html = HttpUtil.fromHtml(HttpUtil 
                            .getHtml( "http://wap.sina.com" )); 
                    msg.what = 0
                } catch (Exception e) { 
                    e.printStackTrace(); 
                    msg.what = 1
               
 
                myHandler.sendMessage(msg); 
           
        }.start(); 

然后让handler处理这个消息
?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
Handler myHandler = new Handler() { 
 
        public void handleMessage(Message msg) { 
            switch (msg.what) { 
            case 0
                textView1.setText(html); 
                progressDialog.dismiss(); 
                break
            case 1
                textView1.setText( "当前无数据" ); 
                progressDialog.dismiss(); 
                break
           
            super .handleMessage(msg); 
       
    }; 


2.更多使用
    
       Handler中分发消息的一些主要方法的说明

        post(Runnable)  //执行某个动作 也就是 排列一个Runnable对象到主线程队列中,

        postAtTime(Runnable,long) 在指定时间(linux时间戳) 执行这个动作

        postDelayed(Runnable long) 延时多少时间执行这个动作

        sendEmptyMessage(int) 发送int消息    sendMessage允许你发送一个带数据的Message对象到handler对应线程的消息队列中

        sendMessage(Message) 发送消息 这个message中可以包含两个int和一个object对象 注意 开销比上面要大

        sendMessageAtTime(Message,long) 在指定时间发送消息

        sendMessageDelayed(Message,long) //延时多少时间后发送这个消息


一个小实例: 使用handler实现 实现在ui线程不断做某些事情例如轮播广告 注意不要做非常耗时的操作 会阻塞UI线程的

?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
private Runnable runnable = new Runnable() {
               
                @Override
                public void run() {
                        if (!isPlay)
                                return ;
                         handler.postDelayed( this , 1000 );
                        //TODO do sth
                 }
        };
        runnable.run();


参考文献
http://www.cnblogs.com/codingmyworld/archive/2011/09/14/2174255.html
http://blog.csdn.net/luoshengyang/article/details/6817933

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值