图解 Android Handler 线程消息机制

从现实生活中理解线程消息机制

android 有一种叫消息队列的说法,这里我们可以这样理解:假如一个隧道就是一个消息队列,那么里面的每一部汽车就是一个一个消息,这里我们先忽略掉超车等种种因素,只那么先进隧道的车将会先出,这个机制跟我们android 的消息机制是一样的。

Android 的线程消息机制

android 在设计的时候引入了 wince 的消息机制,即将每一个消息发送到队列里面,遵循先进先出原则。发送消息并不会阻塞线程,而接收线程会阻塞线程,这是因为 Android 的Handler 机制,当Handler 处理完一个 Message 对象才会接着去取下面一个消息进行处理,如下图:

这里记住:Android里并没有Global的Message Queue数据结构,例如,不同APK里的对象不能透过Massage Queue来交换讯息(Message)。例如:线程A的Handler对象可以传递消息给别的线程,让别的线程B或C等能送消息来给线程A(存于A的Message Queue里)。线程A的Message Queue里的讯息,只有线程A所属的对象可以处理。

案例分析:

经典的歌词同步,这时我们不仅要听到优质的歌曲,还要可以有歌词同步,这时另开一条线程来处理歌词的同步是比较好的解决办法,你可以根据自己的定义,抓取歌曲的duration 在线程中处理歌词的前进或者后退。。。

Demo 分析:

下面我们来实现一个Iphone 上的一个通过按数字后,数字过多消除的按钮事件。事件的原理如下,事件要的效果是这样的,当长按消除按钮后,数字会慢慢消除,过会消除速度会增快,那么实现这个效果我们就需要自己做一个小键盘,我做的键盘效果如下:

我们通过点击 来达到这个效果,使用的是android 的线程机制。实现代码如下:

 

private  Thread thread;
    
private  TextView tv_call_no;
    
protected   static  Runnable Runablerun  =   null ;
    
private  Handler handler;
    
private   int  textLength  =   0 ;
    
private   boolean  isStop  =   true ;

 

 

首先将要使用的数据类型声明在头部,将会使用到 java 的 Thread 和Android Handler 对象,首先实现Runable 对象,代码如下:

 

Runablerun  =   new  Runnable() {

            @Override
            
public   void  run() {
                
//  TODO Auto-generated method stub
                 try  {
                    
int  i  =   0 ;
                    
do  {
                        i
++ ;
                        Thread.sleep(i 
>   15   ?   20  :  100 );
                        Message msg 
=  handler.obtainMessage();
                        msg.arg1 
=  i;
                        msg.sendToTarget(); 
                        
if  (i  ==  textLength) {
                            isStop 
=   false ;
                        }
                    } 
while  (isStop);
                } 
catch  (Exception e) {
                    
//  TODO: handle exception
                }
            }
        };

 

 

上面代码还可以如此写法:

 

    Message msg = new  Message();
    msg.arg1
= i;
    handler.sendMessage(msg);

 

 

第一种写法是message 从handler 类获取,从而可以直接向该handler 对象发送消息,第二种写法是直接调用 handler 的发送消息方法发送消息。不过不管是第一种方法好还是第二种方法好,都要在同样的handler 接收消息,否则会报异常。下面实现handler 对象,代码如下:

 

/**
     * 启动线程
     * 
     * 
@param  tv
     * 
@param  text
     * 
@return
     
*/
    
public  Handler getHandler( final  TextView tv,  final  String text) {
        Handler hand 
=   new  Handler() {
            
public   void  handleMessage(Message msg) {

                tv.setText(text.substring(
0 , text.length()  -  msg.arg1));

                
super .handleMessage(msg); 
            };
        };
        
return  hand;

    }

 

 

这里返回一个handler 对象,实际上是返回去给上面我们的handler 对象使用,这里我把它封装成一个方法,可以让它在每次接收到消息后去使用消息处理文本每次减1

设置的 onTouch 事件,使其在弹出时停止递减:

 

/**
     * 点击back删除之前的数据,跳出就停止删除
     
*/
    OnTouchListener ontouch 
=   new  OnTouchListener() {

        @Override
        
public   boolean  onTouch(View v, MotionEvent event) {
            
//  TODO Auto-generated method stub
            
            String text 
=  tv_call_no.getText().toString();
            
if  (text.length()  ==   0 ) {
                isStop 
=   false ;
                
return   false ;
            }
            
switch  (event.getAction()) {
            
case  MotionEvent.ACTION_DOWN:
                isStop 
=   true ;
                textLength 
=  tv_call_no.getText().length();
                
                handler 
=  getHandler(tv_call_no, text);
                thread 
=   new  Thread(Runablerun);
                thread.start();
                
break ;
            
case  MotionEvent.ACTION_UP:
                isStop 
=   false ;
                
break ;

            }
            
return   false ;
        }
    };

 

 

小结:

  • 1、向哪个Handler 发送消息,就必须在哪个handler 里面接收;
  • 2、直接使用JAVA 的 Thread 是无法更新Android UI的,因为Android View 在设计的时线程是不完全的,不过Android 提供了几种供开发者在线程中更新UI的方法,如下:
    • Activity.runOnUiThread( Runnable )
    • View.post( Runnable )
    • View.postDelayed( Runnable, long )
    • Hanlder
  • 3、直接使用hanlder .post 等方法是在当前主线程里面做操作,而不是另外新建线程,建议使用Thread 线程直接新建另外一个线程或者使用HandlerThread类也可以。
  • 4、记住消息队列的先进先出原则。
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值