Handler的使用(一)

来源:互联网 发布:网络直播平台搭建 编辑:程序博客网 时间:2024/05/01 18:01

概念:

MessageQueue:消息队列,存放消息的地方,按照FIFO(先进先出)规则执行,每一个线程只可以拥有一个MessageQueue,在创建looper对象会创建一个MessageQueue对象

Message:消息对象,MessageQueue中存放的对象,一个MessageQueue中可以包含多个Message对象,可以通过Message.obtain()或Message.obtainMessage()获取Message对象,但是并不一定是直接创建一个新的实例,而是先从消息池中看有没有可用的Message实例,存在则直接取出返回这个实例,如果消息池中没有可用的Message实例,则才用给定的参数创建一个Message对象,调用removeMessage()将message对象从MessageQueue中删除,同时放入到消息池中

Looper:操作MessageQueue.一个Looper对应一个MessageQueue.通过调用Loop.myLooper()可以获得当前线程的Looper对象.Looper从MessageQueue中取出Message后,交给Handler的handleMessage()进行处理.处理完后,调用Message.recycle()将其放入消息池中

Handler:消息的处理者,handler负责将需要传递的信息封转成Message对象,然后调用sendMessage()方法将消息放入到MessageQueue中,当MessageQueue循环到该Message,

调用相应的Handler对象的HandleMessage()方法对其进行处理,Handler都可以共享同一个Looper和MessageQueue

handler类允许你发送消息和处理线程消息队列中的消息及runnable对象。handler实例都是与一个线程和该线程的消息队列一起使用,一旦创建了一个新的handler实例,系统就把该实例与一个线程和该线程的消息队列捆绑起来,这将可以发送消息和runnable对象给该消息队列,并在消息队列出口处处理它们。

handler类有两种主要用途:1。按照时间计划,在未来某时刻,对处理一个消息或执行某个runnable实例。2。把一个对另外线程对象的操作请求放入消息队列中,从而避免线程间冲突。

时间类消息通过如下方法使用: post(Runnable), postAtTime(Runnable, long), postDelayed(Runnable, long), sendEmptyMessage(int), sendMessage(Message), sendMessageAtTime(Message, long), and sendMessageDelayed(Message, long)
methods. post之类函数可以传输一个runnable对象给消息队列,并在到达消息队列后被调用。sendmessage之类函数可以传送一个包含数据的message对象,该message对象可以被Handler类的handleMessage(Message) 方法所处理。

post之类函数和sendmessage之类的函数都可以指定消息的执行时机,是立即执行、稍后一段时间执行,还是在某个确定时刻执行。这可以用来实现超时、消息或其他时间相关的操作。

当一个进程启动时,主线程独立执行一个消息队列,该队列管理着应用顶层的对象(如:activities、broadcast receivers等等)和所有创建的窗口。你可以创建自己的一个线程,并通过handler来与主线程进行通信。这可以通过在新的线程中调用主线程的handler的post和sendmessage操作来实现。

1、布局文件main.xml

[java] view plaincopy
  1. <ProgressBar  
  2.       android:id="@+id/myProBar"  
  3.       style="?android:attr/progressBarStyleHorizontal"  
  4.       android:layout_width="fill_parent"  
  5.       android:layout_height="wrap_content"  
  6.       android:visibility="gone"/>      //将ProgressBar设置为不可见  
  7.     
  8.   <Button  
  9.       android:id="@+id/btnStart"  
  10.       android:layout_width="fill_parent"  
  11.       android:layout_height="wrap_content"  
  12.       android:text="@string/btnStart"/>   

2、Activity文件中的代码如下

[java] view plaincopy
  1.   / /声明控件变量  
  2.      ProgressBar proBar;  
  3.      Button btnStart;  
  4.      int i=0;  
  5.     @Override  
  6.     public void onCreate(Bundle savedInstanceState) {  
  7.        super.onCreate(savedInstanceState);  
  8.        setContentView(R.layout.main);  
  9.          
  10.        //根据控件的ID得到控件的对象  
  11.   
  12.        roBar=(ProgressBar)this.findViewById(R.id.myProBar);  
  13.        btnStart=(Button)this.findViewById(R.id.btnStart);  
  14.          
  15.        //为btnStart按钮绑定监听器  
  16.        btnStart.setOnClickListener(new View.OnClickListener() {  
  17.        @Override  
  18.         public void onClick(View arg0) {  
  19.             proBar.setVisibility(View.VISIBLE);  
  20.             updateBarHandler.post(updateThread);  
  21.            }    
  22.   
  23.      //使用匿名内部类来复写Handle当中的handlerMessage()方法  
  24.        Handler updateBarHandler=new Handler(){  
  25.        @Override  
  26.        public void handlerMessage(Message msg) {  
  27.   
  28.        //将进度条设置为可见  
  29.        proBar.setProgress(msg.arg1);  
  30.        
  31.       //调用Handler的post()方法,将要执行的线程对象添加到队列当中  
  32.        updateBarHandler.post(updateThread);  
  33.          }  
  34.        };  
  35.        //线程类,该类使用匿名内部类的方式进行声明  
  36.          Runnable updateThread=new Runnable()  
  37.          {  
  38.        //将要执行的操作写在线程对象的run()方法当中  
  39.             @Override  
  40.              public void run() {  
  41.               i+=10;  
  42.         //得到一个消息,Message类是由android操作系统提供  
  43.               Message msg=updateBarHandler.obtainMessage();  
  44.         //可以用arg1和arg2这两个成员变量传递消息  
  45.               msg.arg1=i;  
  46.              try{  
  47.         //睡眠1秒  
  48.               Thread.sleep(1000);   
  49.                }  
  50.            catch(InterruptedException e) {  
  51.                 e.printStackTrace();  
  52.                 }  
  53.        //将msg对象加入到消息队列当中(加入到消息队列中就立刻返回,不管消息是否被处理(异步),会调用handleMessage()方法)  
  54.        updateBarHandler.sendMessage(msg);     
  55.         if(i==100)  
  56.      {  
  57.      //将线程对象从队列中移除  
  58.       updateBarHandler.removeCallbacks(updateThread);  
  59.      }  
  60.     }  
  61.    };  
  62.  });  
  63.   
  64. }  

3、运行结果

 

 

1.Handler与线程

  实际上Handler与Activity处于同一线程当中

[java] view plaincopy
  1. public void onCreate(Bundle savedInstanceState) {  
  2.        super.onCreate(savedInstanceState);  
  3.        Handler handler=new Handler();  
  4.        handler.post(r);  
  5.          
  6.        setContentView(R.layout.main);  
  7.          
  8.        System.out.println("activity--->"+Thread.currentThread().getId());  
  9.     System.out.println("activity--->"+Thread.currentThread().getName());  
  10.   
  11.    }  
  12.      
  13.  Runnable r=new Runnable(){  
  14.   
  15. @Override  
  16. public void run() {  
  17.     System.out.println("handler--->"+Thread.currentThread().getId());  
  18.     System.out.println("handlerName--->"+Thread.currentThread().getName());  
  19.       
  20.     try {  
  21.         Thread.sleep(10000);  
  22.     } catch (InterruptedException e) {  
  23.       
  24.         e.printStackTrace();  
  25.     }  
  26. }  

handersetCotentView()之前,所有要等待10秒,Activity中的内容才显示处理,并且输出的id和name相同,则说明Handler没有启动新线程,

2.在新线程当中处理消息方法,(需要使用Looper对象,改对象提供了循环的从队列中取消息的这种功能),并使用Bundle

[java] view plaincopy
  1. package wei.cao.handler;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5. import android.os.Handler;  
  6. import android.os.HandlerThread;  
  7. import android.os.Looper;  
  8. import android.os.Message;  
  9.   
  10. public class Handler_03 extends Activity {  
  11. @Override  
  12. protected void onCreate(Bundle savedInstanceState) {  
  13.     super.onCreate(savedInstanceState);  
  14.     setContentView(R.layout.main);  
  15.       
  16.     System.out.println("Activity--->"+Thread.currentThread().getId());  
  17.     //生成一个HandlerThread对象,实现了使用looper来处理消息的功能,这个类由Android应用程序框架提供  
  18.     HandlerThread handlerThread=new HandlerThread("handler_thread");  
  19.     //在使用HandlerThread的getLooper()方法之前,必须先调用该类的start()方法,否在调用getLooper()方法返回null  
  20.     handlerThread.start();  
  21.       
  22.     MyHandler myHandler=new MyHandler(handlerThread.getLooper());  
  23.     //将Msg发送到目标对象,所谓的目标对象,就是生成msg对象的hand对象  
  24.     Message msg=myHandler.obtainMessage();  
  25.     //使用Bundler对象来传递数据  
  26.     Bundle b=new Bundle();  
  27.     b.putString("name""wei_cao");  
  28.     b.putInt("age"10);  
  29.     msg.obj="abc";  
  30.     msg.setData(b);  
  31.     msg.sendToTarget();  
  32.       
  33. }  
  34.  class MyHandler extends Handler  
  35.  {  
  36.      public MyHandler(Looper looper)  
  37.      {  
  38.          super(looper);  
  39.      }  
  40.   
  41.     @Override  
  42.     public void handleMessage(Message msg) {  
  43.         String str=(String)msg.obj;  
  44.         //从消息中取出Bundle对象  
  45.         Bundle b=msg.getData();  
  46.         String name=b.getString("name");  
  47.         int age=b.getInt("age");  
  48.         System.out.println("name is "+name+"age is "+age+"str is "+str);  
  49.         System.out.println("Handler--->"+Thread.currentThread().getId());  
  50.         System.out.println("handleMessage");  
  51.     }  
  52.        
  53.        
  54.  }  


原创粉丝点击