异步消息处理 handler

当我们在处理下载或是其他需要长时间执行的任务时,如果直接把处理函数放Activity的OnCreate或是OnStart中,会导致执行过程中整个Activity无响应,如果时间过长,程序还会挂掉。Handler就是把这些功能放到一个单独的线程里执行,与Activity互不影响。因此我们需要另外起动一个线程来处理长耗时操作,而主线程则不受其影响,在耗时操作完结发送消息给主线程,主线程再做相应处理。那么线程之间的消息传递和异步处理用的就是Handler。

Andrioid中费时的操作要放在子线程中处理,更新UI要放在主线程中进行。如果根据子线程的动作或进度要更新UI,在子线程中进行是不安全的,这时需要用到handler。Handler运行在主线程(UI线程)中,与子线程通过Message对象来传递数据。Handler接收子线程传过来的Message对象(子线程通过sendMessage()方法传递),把这些消息放入主线程队列中,配合主线程更新UI。

Handler的作用:安排消息或Runnable在某个主线程中的某个地方执行;安排一个动作在不同的线程中执行。

 

例1: 一个应用程序中有2个按钮(start、end),当点击start按钮时,执行一个线程,这个线程在控制台输出一串字符串,并且每隔3秒再执行一次线程,直到点击end按钮为止,线程停止。

步骤为:

1、     在Activity中,创建一个Handler对象

Handler handler = new Handler();

2、     在Activity中,创建一个Runnable对象

  a) 以匿名内部类的方式

       b) 将要执行的操作写在Runnable对象中的run()方法中

          i. 打印出一句话

          ii. 调用Runnable对象的postDelayed()方法

 

Runnable updateThread = new Runnable(){ 
  
//将要执行的操作写在线程对象的run方法当中 
  
public void run(){ 
  
System.out.println("updateThread"); 
  
//调用Handler的postDelayed()方法   ,将要执行的线程对象放入到队列当中,待时间结束后,运行制定的线程对象 
  
handler.postDelayed(updateThread, 3000); 
  
} 
  
}; 

 
             

3、 在Activity中,编写start按钮需要的监听器,并绑定

       a) 在这个监听器的Onclick()方法中,调用Handler的post()方法,将要执行的线程对象放到队列当中。

handler.post(updateThread);

4、 在Activity中,编写end按钮需要的监听器,并帮定

       a) 在这个监听器的Onclick()方法中,调用Handler的removeCallbacks ()方法,删除队列当中未执行的线程对象。

handler.removeCallbacks(updateThread);

 

 

例2:一个应用程序中有一个进度条和一个按钮,当点击按钮后,每隔一秒钟进度条前进一部分.

         步骤为:

1、   创建线程对象,通过匿名内部类的方式进行声明。

i. 声明一个变量用来设置进度条的进度

ii. 重写线程类的run方法(),里面编写要执行的操作

a. 打印一个字符串;

b. 进度条的值增加;

c. 得到一个消息对象;

d. 设置消息对象arg1的值;

e. 让线程休眠一秒钟;

 f. 将消息对象放入到消息队列中;

 g. 判断,如果进度条的值等于100,则将线程对象从队列中移除。

Runnable updateThread = new Runnable(){ 
  
//将要执行的操作写在线程对象的run方法当中 
  
public void run(){ 
  
System.out.println("updateThread"); 
  
//调用Handler的postDelayed()方法   ,将要执行的线程对象放入到队列当中,待时间结束后,运行制定的线程对象 
  
handler.postDelayed(updateThread, 3000); 
  
} 
  
}; 


2、使用匿名内部类的方法生成Handler对象,重写Handler对象的handlerMessage(Message msg)方法。  

i. 这个方法传入了一个Message对象,即消息对象,首先设置进度条的进度(这个值是Messag对象里面的一个成员变量arg1);

 ii. 将要执行的线程对象放入到队列当中。

 
  
//使用匿名内部类来复写Handler当中的handlerMessage()方法 
  
Handler updateBarHandler = new Handler(){ 
  
@Override 
  
public void handleMessage(Message msg) { 
  
progressBar.setProgress(msg.arg1); 
  
updateBarHandler.post(updateThread);   //将要执行的线程放入到队列当中 
  
} 
  
}; 
 


注意: 使用Handler对象的post方法家在Runnable对象时不会新建线程,只是在当前线程中执行run方法。若要创建新的线程,需要使用Thread,将runnable对象作为参数传入。

Thread t = new Thread(r);

t.start();

 

 

为了使Activity和复杂的数据处理位于不同的线程中,可以使用HandlerThread,实现使用Looper来处理消息队列的功能,注意使用HandlerThread对象的getLooper方法之前,必须先调用该类的start方法。Looper在线程中运行一个消息循环,HandlerThread使用一个消息循环启用一个线程,而Handler用于处理消息。

 

Android中每一个Thread都跟着一个Looper,Looper可以帮助Thread维护一个消息队列,但是Looper和Handler没有什么关系。Android还提供了一个Thread继承类HanderThread可以帮助我们处理,在HandlerThread对象中可以通过getLooper方法获取一个Looper对象控制句柄,我们可以将其这个Looper对象映射到一个Handler中去来实现一个线程同步机制。

 

Messge对象的sendToTarget方法是将message发送到目标对象,所谓的目标对象就是生成改messgae对象的handler对象。

HandlerThread handlerThread = new   HandlerThread("handlerThread");//生成handlerThread对象
  
          handlerThread.start();//启动handlerThread对象
  
        MyHandler   myhandler = new   MyHandler(handlerThread.getLooper());//使用handlerThread对象的looper对象作为参数,生成Myhandler对象(Handler的子类)。
  
        Message   msg = myhandler.obtainMessage();
  
        msg.arg1   = 1;
  
          msg.sendToTarget();
  
 
  
class MyHandler extends Handler{
  
                   public   MyHandler(){
  
                   }
  
                     //编写以Looper对象为参数的构造函数
  
                   public   MyHandler(Looper looper){
  
                                   super(looper);
  
                   }
  
 
  
                       @Override //重写handleMessage方法
  
                       public void handleMessage(Message msg) {
  
                                     // TODO Auto-generated method stub
  
                                     super.handleMessage(msg);
  
                                     System.out,println(msg.arg1);
  
                                     System.out.println("MyHandler---> id: " +   Thread.currentThread().getId());
  
                                     System.out.println("MyHandler---> name: " +   Thread.currentThread().getName());
  
                       }
  
    }


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值