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

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、记住消息队列的先进先出原则。

更多相关文章

  1. Android调用WebService系列之KSoap2对象解析
  2. Android(安卓)多线程-----AsyncTask详解
  3. Android的View类使用
  4. Android(安卓)的网络编程
  5. Android消息处理两大利器:Handler and Looper
  6. Android线程模型解析(包括UI的更新)
  7. android中的UI单线程模型
  8. Android调用WebService系列之KSoap2对象解析
  9. Android的内存泄漏和调试

随机推荐

  1. Android中LayoutParams总结和用法
  2. 为Android加入busybox工具
  3. android布局tips,基础知识搜集
  4. android shape的使用
  5. android HAL介绍
  6. Android中的坐标系以及获取坐标的方法
  7. Android(安卓)各种实现Tab效果的实现方式
  8. Android(安卓)内核简单分析
  9. Android(安卓)开发笔记 —— AndroidStud
  10. Android层次化安全架构及核心组件概览