Handler

来源:互联网 发布:中国cms哪个好 编辑:程序博客网 时间:2024/05/21 01:57
一、Handler的定义:

          主要接受子
线程发送的数据, 并用此数据配合主线程更新UI.

          解释: 当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的UI控件,进行事件分发, 比如说, 你要是点击一个 Button ,Android会分发事件到Button上,来响应你的操作。  如果此时需要一个耗时的操作,例如: 联网读取数据,    或者读取本地较大的一个文件的时候,你不能把这些操作放在主线程中,,如果你放在主线程中的话,界面会出现假死现象, 如果5秒钟还没有完成的话,,会收到Android系统的一个错误提示  "强制关闭".  这个时候我们需要把这些耗时的操作,放在一个子线程中,因为子线程涉及到UI更新,,Android主线程是线程不安全的,也就是说,更新UI只能在主线程中更新,子线程中操作是危险的. 这个时候,Handler就出现了.,来解决这个复杂的问题 ,    由于Handler运行在主线程中(UI线程中),  它与子线程可以通过Message对象来传递数据, 这个时候,Handler就承担着接受子线程传过来的(子线程用sedMessage()方法传弟)Message对象,(里面包含数据)  , 把这些消息放入主线程队列中,配合主线程进行更新UI。

二、Handler一些特点

        handler可以分发Message对象和Runnable对象到主线程中, 每个Handler实例,都会绑定到创建他的线程中(一般是位于主线程),
        它有两个作用: (1):  安排消息或Runnable 在某个主线程中某个地方执行, (2)安排一个动作在不同的线程中执行
      
        Handler中分发消息的一些方法
        post(Runnable)
        postAtTime(Runnable,long)
        postDelayed(Runnable long)
        sendEmptyMessage(int)
        sendMessage(Message)
        sendMessageAtTime(Message,long)
        sendMessageDelayed(Message,long)

        以上post类方法允许你排列一个Runnable对象到主线程队列中,
        sendMessage类方法, 允许你安排一个带数据的Message对象到队列中,等待更新.

三、Handler实例

      (1) 子类需要继承Hendler类,并重写handleMessage(Message msg) 方法, 用于接受线程数据

      以下为一个实例,它实现的功能为 : 通过线程修改界面Button的内容
  1. public class MyHandlerActivity extends Activity {
  2.     Button button;
  3.     MyHandler myHandler;

  4.     protected void onCreate(Bundle savedInstanceState) {
  5.         super.onCreate(savedInstanceState);
  6.         setContentView(R.layout.handlertest);

  7.         button = (Button) findViewById(R.id.button);
  8.         myHandler = new MyHandler();
  9.         // 当创建一个新的Handler实例时, 它会绑定到当前线程和消息的队列中,开始分发数据
  10.         // Handler有两个作用, (1) : 定时执行Message和Runnalbe 对象
  11.         // (2): 让一个动作,在不同的线程中执行.

  12.         // 它安排消息,用以下方法
  13.         // post(Runnable)
  14.         // postAtTime(Runnable,long)
  15.         // postDelayed(Runnable,long)
  16.         // sendEmptyMessage(int)
  17.         // sendMessage(Message);
  18.         // sendMessageAtTime(Message,long)
  19.         // sendMessageDelayed(Message,long)
  20.       
  21.         // 以上方法以 post开头的允许你处理Runnable对象
  22.         //sendMessage()允许你处理Message对象(Message里可以包含数据,)

  23.         MyThread m = new MyThread();
  24.         new Thread(m).start();
  25.     }

  26.     /**
  27.     * 接受消息,处理消息 ,此Handler会与当前主线程一块运行
  28.     * */

  29.     class MyHandler extends Handler {
  30.         public MyHandler() {
  31.         }

  32.         public MyHandler(Looper L) {
  33.             super(L);
  34.         }

  35.         // 子类必须重写此方法,接受数据
  36.         @Override
  37.         public void handleMessage(Message msg) {
  38.             // TODO Auto-generated method stub
  39.             Log.d("MyHandler", "handleMessage......");
  40.             super.handleMessage(msg);
  41.             // 此处可以更新UI
  42.             Bundle b = msg.getData();
  43.             String color = b.getString("color");
  44.             MyHandlerActivity.this.button.append(color);

  45.         }
  46.     }

  47.     class MyThread implements Runnable {
  48.         public void run() {

  49.             try {
  50.                 Thread.sleep(10000);
  51.             } catch (InterruptedException e) {
  52.                 // TODO Auto-generated catch block
  53.                 e.printStackTrace();
  54.             }

  55.             Log.d("thread.......", "mThread........");
  56.             Message msg = new Message();
  57.             Bundle b = new Bundle();// 存放数据
  58.             b.putString("color", "我的");
  59.             msg.setData(b);

  60.             MyHandlerActivity.this.myHandler.sendMessage(msg); // 向Handler发送消息,更新UI

  61.         }
  62.     }

  63. }
复制代码
 
 

handler(java中名称)编辑

本词条缺少概述信息栏名片图,补充相关内容使词条更完整,还能快速升级,赶紧来编辑吧!

目录

1特点

2分发消息方法

3和多线程

1特点编辑

1. 传递Message。用于接受子线程发送的数据, 并用此数据配合主线程更新UI。
在Android中,对于UI的操作通常需要放在主线程中进行操作。如果在子线程中有关于UI的操作,那么就需要把数据消息作为一个Message对象发送到消息队列中,然后,由Handler中的handlerMessage方法处理传过来的数据信息,并操作UI。当然,Handler对象是在主线程中初始化的,因为它需要绑定在主线程的消息队列中。
类sendMessage(Message msg)方法实现发送消息的操作。 在初始化Handler对象时重写的handleMessage方法来接收Message并进行相关操作。
2. 传递Runnable对象。用于通过Handler绑定的消息队列,安排不同操作的执行顺序。
Handler对象在进行初始化的时候,会默认的自动绑定消息队列。利用类post方法,可以将Runnable对象发送到消息队列中,按照队列的机制按顺序执行不同的Runnable对象中的run方法。[1] 

2分发消息方法编辑

post(Runnable)
postAtTime(Runnable,long)
postDelayed(Runnable,long)
sendEmptyMessage(int)
sendMessage(Message)
sendMessageAtTime(Message,long)
sendMessageDelayed(Message,long)[2] 

3和多线程编辑

post方法虽然发送的是一个实现了Runnable接口的类对象,但是它并非创建了一个新线程,而是执行了该对象中的run方法。也就是说,整个run中的操作和主线程处于同一个线程。
这样对于那些简单的操作,似乎并不会影响。但是对于耗时较长的操作,当它被加入到消息队列中之后执行会占用很长的时间,以至于处于同一线程的其他操作无法继续执行,就会出现“假死”。为了解决这个问题,就需要使得handler绑定到一个新开启线程的消息队列上,在这个处于另外线程的上的消息队列中处理传过来的Runnable对象和消息。
这样,当使用sendMessage方法传递消息或者使用post方法传递Runnable对象时,就会把它们传递到与handler对象绑定的处于另外一个线程的消息队列中,它们将在另外的消息队列中被处理。而主线程还会在发送操作完成时候继续进行,不会影响当前的操作。
这里需要注意,这里用到的多线程并非由Runnable对象开启的,而是ThreadHandler对象开启的。Runnable对象只是作为一个封装了操作的对象被传递,并未产生新线程。
Handler初探
2011-01-01 18:36:04
标签:多线程 Handler 休闲 android 职场
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://52android.blog.51cto.com/2554429/470542

    Android中有着和J2SE同样优秀的多线程支持,可以把那些耗时较多的操作放在新线程中操作。但是当新线程中有涉及到操作UI的操作时,就会对主线程产生危险,因此,Android提供了Handler作为主线程和子线程的纽带。同时,Handler对象初始化后,就默认与对它初始化的进程的消息队列绑定,因此可以利用Handler所包含的消息队列,制定一些操作的顺序。

   根据SDK文档的说明:“A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue.”由此可以清楚的知道,可以把消息和Runnble对象发送到与Handler对象所关联的消息队列中去。

    

     下面,就Handler的以上两点作用,分别进行讨论。

    1. 传递Message。用于接受子线程发送的数据, 并用此数据配合主线程更新UI。

    在Android中,对于UI的操作通常需要放在主线程中进行操作。如果在子线程中有关于UI的操作,那么就需要把数据消息作为一个Message对象发送到消息队列中,然后,有Handler中的handlerMessge方法处理传过来的数据信息,并操作UI。当然,Handler对象是在主线程中初始化的,以为它需要绑定在主线程的消息队列中。

    类sendMessage(Message msg)方法实现发送消息的操作。 在初始化Handler对象时重写的handleMessage方法来接收Messgae并进行相关操作。

  

 
 

  1. //Handler处理子线程消息代码示例:  
  2.  
  3. public class Activity01 extends Activity  
  4. {  
  5.     //声明ProgressBar对象  
  6.     private ProgressBar m_ProgressBar;  
  7.     private ProgressBar m_ProgressBar2;  
  8.     private Button mButton01;  
  9.     protected static final int GUI_STOP_NOTIFIER = 0x108;  
  10.     protected static final int GUI_THREADING_NOTIFIER = 0x109;  
  11.     public int intCounter=0;  
  12.     /** Called when the activity is first created. */ 
  13.     @Override 
  14.     public void onCreate(Bundle savedInstanceState)  
  15.     {  
  16.         super.onCreate(savedInstanceState);  
  17.         //设置窗口模式,,因为需要显示进度条在标题栏  
  18.         requestWindowFeature(Window.FEATURE_PROGRESS);  
  19.         setProgressBarVisibility(true);  
  20.         setContentView(R.layout.main);  
  21.           
  22.         //取得ProgressBar  
  23.         m_ProgressBar = (ProgressBar) findViewById(R.id.ProgressBar01);  
  24.         m_ProgressBar2= (ProgressBar) findViewById(R.id.ProgressBar02);  
  25.         mButton01 = (Button)findViewById(R.id.Button01);   
  26.           
  27.         m_ProgressBar.setIndeterminate(false);  
  28.         m_ProgressBar2.setIndeterminate(false);  
  29.           
  30.         //当按钮按下时开始执行,  
  31.         mButton01.setOnClickListener(new Button.OnClickListener()  
  32.         {  
  33.           @Override 
  34.           public void onClick(View v)  
  35.           {  
  36.             // TODO Auto-generated method stub  
  37.                 
  38.               //设置ProgressBar为可见状态  
  39.               m_ProgressBar.setVisibility(View.VISIBLE);  
  40.               m_ProgressBar2.setVisibility(View.VISIBLE);  
  41.               //设置ProgressBar的最大值  
  42.               m_ProgressBar.setMax(100);  
  43.               //设置ProgressBar当前值  
  44.               m_ProgressBar.setProgress(0);  
  45.               m_ProgressBar2.setProgress(0);  
  46.  
  47.               //通过线程来改变ProgressBar的值  
  48.   new Thread(new Runnable() {  
  49.      public void run()  
  50.         {  
  51.      for (int i = 0; i < 10; i++)  
  52.         {  
  53.            try 
  54.            {  
  55.                  intCounter = (i + 1) * 20;  
  56.                  Thread.sleep(1000);  
  57.  
  58.             if (i == 4)  
  59.             {  
  60.             Message m = new Message();  
  61.  
  62.              m.what = Activity01.GUI_STOP_NOTIFIER;  
  63.             Activity01.this.myMessageHandler.sendMessage(m);
  64. //将message发送到消息队列  
  65.               break;  
  66.              }  
  67.             else 
  68.            {  
  69.            Message m = new Message();  
  70.            m.what = Activity01.GUI_THREADING_NOTIFIER;  
  71.            Activity01.this.myMessageHandler.sendMessage(m);  
  72. //将message发送到消息队列  
  73.                                 }  
  74.                             }  
  75.                             catch (Exception e)  
  76.                             {  
  77.                                 e.printStackTrace();  
  78.                             }  
  79.                         }  
  80.                     }  
  81.                 }).start();  
  82.             }  
  83.         });  
  84.     }  
  85.  
  86. //通过匿名类复写Handler类中的handleMessage方法,用于接收传递到消息队列中的Message,并进行UI操作。
  87.       Handler myMessageHandler = new Handler()  
  88.       {  
  89.         // @Override   
  90.           public void handleMessage(Message msg)  
  91.           {  
  92.               switch (msg.what)  
  93.               {  
  94.               //ProgressBar已经是对大值  
  95.               case Activity01.GUI_STOP_NOTIFIER:  
  96.                   m_ProgressBar.setVisibility(View.GONE);  
  97.                   m_ProgressBar2.setVisibility(View.GONE);  
  98.                   Thread.currentThread().interrupt();  
  99.                   break;  
  100.               case Activity01.GUI_THREADING_NOTIFIER:  
  101.                   if (!Thread.currentThread().isInterrupted())  
  102.                   {  
  103.                       // 改变ProgressBar的当前值  
  104.                       m_ProgressBar.setProgress(intCounter);  
  105.                       m_ProgressBar2.setProgress(intCounter);  
  106.                         
  107.                       // 设置标题栏中前景的一个进度条进度值  
  108.                       setProgress(intCounter*100);  
  109.                       // 设置标题栏中后面的一个进度条进度值  
  110.                       setSecondaryProgress(intCounter*100);//  
  111.                   }  
  112.                   break;  
  113.               }  
  114.               super.handleMessage(msg);  
  115.          }  
  116.       };  
  117. }  

    以上的例子中,子线程只是对进度条的参数进行了变更,并将结果以message形式发送到消息队列中去,子线程的内部并未进行UI操作,而是在重写的Handler的handlerMessage方法中操作了UI界面。

    2. 传递Runnable对象。用于通过Handler绑定的消息队列,安排不同操作的执行顺序。

    Handler对象在进行初始化的时候,会默认的自动绑定消息队列。利用类post方法,可以将Runnable对象发送到消息队列中,按照队列的机制按顺序执行不同的Runnable对象中的run方法。

   

 

  1. public class HandlerActivity extends Activity {  
  2.     /** Called when the activity is first created. */ 
  3.     //声明两个按钮控件  
  4.     private Button startButton = null;  
  5.     private Button endButton = null;  
  6.     @Override 
  7.     public void onCreate(Bundle savedInstanceState) {  
  8.         super.onCreate(savedInstanceState);  
  9.         setContentView(R.layout.main);  
  10.         //根据控件的ID得到代表控件的对象,并未这两个按钮设置相应的监听器  
  11.         startButton = (Button)findViewById(R.id.startButton);  
  12.         startButton.setOnClickListener(new StartButtonListener());  
  13.         endButton = (Button)findViewById(R.id.endButton);  
  14.         endButton.setOnClickListener(new EndButtonListener());  
  15.           
  16.     }  
  17.     class StartButtonListener implements OnClickListener{  
  18.  
  19.         @Override 
  20.         public void onClick(View v) {  
  21.             //调用Handler的post方法,将要执行的线程对象添加到队列当中  
  22.             handler.post(updateThread);  
  23.         }  
  24.           
  25.     }  
  26.       
  27.     class EndButtonListener implements OnClickListener{  
  28.  
  29.         @Override 
  30.         public void onClick(View v) {  
  31.             handler.removeCallbacks(updateThread);  
  32.         }  
  33.           
  34.     }  
  35.     //创建一个Handler对象  
  36.     Handler handler  = new Handler();  
  37.     //将要执行的操作写在线程对象的run方法当中  
  38.     Runnable updateThread =  new Runnable(){  
  39.  
  40.         @Override 
  41.         public void run() {  
  42.             System.out.println("UpdateThread");  
  43.             //在run方法内部,执行postDelayed或者是post方法  
  44.             handler.postDelayed(updateThread, 3000);  
  45.         }  
  46.           
  47.     };  

    程序的运行结果就是每隔3秒钟,就会在控制台打印一行UpdateTread。这是因为实现了Runnable接口的updateThread对象进入了空的消息队列即被立即执行run方法,而在run方法的内部,又在3000ms之后将其再次发送进入消息队列中。

   3. Handler和多线程

    post方法虽然发送的是一个实现了Runnable接口的类对象,但是它并非创建了一个新线程,而是执行了该对象中的run方法。也就是说,整个run中的操作和主线程处于同一个线程。

    这样对于那些简单的操作,似乎并不会影响。但是对于耗时较长的操作,当它被加入到消息队列中之后执行会占用很长的时间,以至于处于同一线程的其他操作无法继续执行,就会出现“假死”。为了解决这个问题,就需要使得handler绑定到一个新开启线程的消息队列上,在这个处于另外线程的上的消息队列中处理传过来的Runnable对象和消息。SDK文档中也提供了相关说明:

     When a process is created for your application, its main thread is dedicated to running a message queue that takes care of managing the top-level application objects (activities, broadcast receivers, etc) and any windows they create. You can create your own threads, and communicate back with the main application thread through a Handler. This is done by calling the same post or sendMessage methods as before, but from your new thread. The given Runnable or Message will than be scheduled in the Handler's message queue and processed when appropriate.

     具体操作方法如下:

 
 

  1. public class HandlerTest2 extends Activity {  
  2.  
  3.     @Override 
  4.     protected void onCreate(Bundle savedInstanceState) {  
  5.         // TODO Auto-generated method stub  
  6.     super.onCreate(savedInstanceState);  
  7.     setContentView(R.layout.main);  
  8.     //打印了当前线程的ID  
  9.     System.out.println("Activity-->" + Thread.currentThread().getId());  
  10.     //生成一个HandlerThread对象  
  11.     HandlerThread handlerThread = new HandlerThread("handler_thread");  
  12.     //在使用HandlerThread的getLooper()方法之前,必须先调用该类的start(),同时开启一个新线程;  
  13.     handlerThread.start();
  14. //将由HandlerThread获取的Looper传递给Handler对象,即由处于另外线程的Looper代替handler初始化时默认绑定的消息队列来处理消息。  
  15.     MyHandler myHandler = new MyHandler(handlerThread.getLooper());  
  16.     Message msg = myHandler.obtainMessage();  
  17.     //将msg发送到目标对象,所谓的目标对象,就是生成该msg对象的handler对象  
  18.     Bundle b = new Bundle();  
  19.     b.putInt("age"20);  
  20.     b.putString("name""Jhon");  
  21.     msg.setData(b);  
  22.     msg.sendToTarget();  //将msg发送到myHandler
  23.     }  
  24.       
  25. //定义类
  26.     class MyHandler extends Handler{  
  27.     public MyHandler(){  
  28.               
  29.     }  
  30.     public MyHandler(Looper looper){  
  31.         super(looper);  
  32.     }  
  33.     @Override 
  34.     public void handleMessage(Message msg) {  
  35.         Bundle b = msg.getData();  
  36.         int age = b.getInt("age");  
  37.         String name = b.getString("name");  
  38.         System.out.println("age is " + age + ", name is" + name);  
  39.         System.out.println("Handler--->" + Thread.currentThread().getId());  
  40.         System.out.println("handlerMessage");  
  41.         }  
  42.     }  
  43. }  

    这样,当使用sendMessage方法传递消息或者使用post方法传递Runnable对象时,就会把它们传递到与handler对象绑定的处于另外一个线程的消息队列中,它们将在另外的消息队列中被处理。而主线程还会在发送操作完成时候继续进行,不会影响当前的操作。

    这里需要注意,这里用到的多线程并非由Runnable对象开启的,而是ThreadHandler对象开启的。Runnable对象只是作为一个封装了操作的对象被传递,并未产生新线程。

Android Handler机制

分类: android应用开发 61220人阅读 评论(45)收藏 举报
androidthreadcallbacknull数据结构string

在android中提供了一种异步回调机制Handler,使用它,我们可以在完成一个很长时间的任务后做出相应的通知

handler基本使用:

在主线程中,使用handler很简单,new一个Handler对象实现其handleMessage方法,在handleMessage中
提供收到消息后相应的处理方法即可,这里不对handler使用进行详细说明,在看本博文前,读者应该先掌握handler的基本使用,我这里主要深入描述handler的内部机制

.现在我们首先就有一个问题,我们使用myThreadHandler.sendEmptyMessage(0);发送一个message对象,那么Handler是如何接收该message对象并处理的呢?我先画一个数据结构图:

从这个图中我们很清楚可以看到调用sendEmptyMessage后,会把Message对象放入一个MessageQueue队列,该队列属于某个Looper对象,每个Looper对象通过ThreadLocal.set(new Looper())跟一个Thread绑定了,Looper对象所属的线程在Looper.Loop方法中循环执行从MessageQueue队列读取Message对象,并把Message对象交由Handler处理,调用Handler的dispatchMessage方法。

现在我们再来看一下使用Handler的基本实现代码:

// 主线程中新建一个handler
normalHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
btnSendMsg2NormalHandler.setText("normalHandler");
Log.d(Constant.TAG, MessageFormat.format("Thread[{0}]--normalHandler handleMessage run...", Thread.currentThread()
.getName()));
}
};

...
//发送消息到hanlder
myThreadHandler.sendEmptyMessage(0);

你现在已经很清楚了sendEmptyMessage到handleMessage的过程,途中经过Looper.MessageQueue队列,转由Looper所在的线程去处理了,这是一个异步的过程,当然Looper所在的线程也可以是sendEmptyMessage所在的线程。

看了上面你也许还是迷惑不解,那么什么要Looper了,跟我们要用的Handler又有啥鸟关系呢?

我在前面一直强调在主线程中使用handler,为什么要这么说呢,因为你在自己new一个新线程中去像我前面那样简单建立一个Handler,程序执行是会报错的:

java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:121)
at com.cao.android.demos.handles.HandleTestActivity$MyThread$1.<init>(HandleTestActivity.java:86)
at com.cao.android.demos.handles.HandleTestActivity$MyThread.run(HandleTestActivity.java:86)

为什么在主线程中不会报错,而在自己新见的线程中就会报这个错误呢?很简单,因为主线程它已经建立了Looper,你可以打开ActivityThread的源码看一下:

public static final void main(String[] args) {
SamplingProfilerIntegration.start();

Process.setArgV0("<pre-initialized>");

Looper.prepareMainLooper();

ActivityThread thread = new ActivityThread();
thread.attach(false);

Looper.loop();

if (Process.supportsProcesses()) {
throw new RuntimeException("Main thread loop unexpectedly exited");
}

thread.detach();
String name = (thread.mInitialApplication != null)
? thread.mInitialApplication.getPackageName()
: "<unknown>";
Slog.i(TAG, "Main thread of " + name + " is now exiting");
}

在main函数中它已经做了这个事情了,为什么要调用 Looper.prepareMainLooper(); Looper.loop();我们可以进去看一下,在prepareMainLooper方法中新建了一个looper对象,并与当前进程进行了绑定,而在Looper.loop方法中,线程建立消息循环机制,循环从MessageQueue获取Message对象,调用 msg.target.dispatchMessage(msg);进行处理msg.target在myThreadHandler.sendEmptyMessage(0)设置进去的,因为一个Thead中可以建立多个Hander,通过msg.target保证MessageQueue中的每个msg交由发送message的handler进行处理,那么Handler又是怎样与Looper建立联系的呢,在Handler构造函数中有这样一段代码:

mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;

在新建Handler时需要设置mLooper成员,Looper.myLooper是从当前线程中获取绑定的Looper对象:

public static final Looper myLooper() {
return
(Looper)sThreadLocal.get();
}

若Looper对象没有创建,就会抛异常"Can't create handler inside thread that has not called Looper.prepare()"
这跟我前面讲的是一致的。所以我们在一个新线程中要创建一个Handler就需要这样写:

class MyThread extends Thread {

public void run() {
Log.d(Constant.TAG, MessageFormat.format("Thread[{0}]-- run...", Thread
.currentThread().getName()));
// 其它线程中新建一个handler
Looper.prepare();//
创建该线程的Looper对象,用于接收消息,在非主线程中是没有looper的所以在创建handler前一定要使用prepare()创建一个Looper
myThreadHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
Log.d(Constant.TAG, MessageFormat.format("Thread[{0}]--myThreadHandler handleMessage run...", Thread
.currentThread().getName()));
}
};
Looper.myLooper().loop();//建立一个消息循环,该线程不会退出
}
}

现在,你应该对Handler的机制有所了解了吧,若有什么疑问,欢迎在评论中提出

在其它线程中Handler使用主线程的Looper

前面我说了在新线程中要新建一个Handler需要调用Looper.prepare();也有另一种方法就是使用主线程中的Looper,那就不必新建Looper对象了:

threadMainLoopHandler =new Handler(Looper.getMainLooper()){
public void handleMessage(android.os.Message msg) {
Log.d(Constant.TAG, MessageFormat.format("Thread[{0}]--threadMainLoopHandler handleMessage run...", Thread
.currentThread().getName()));
}
//该handleMessage方法将在mainthread中执行
};

这时候注意不要在handleMessage做太多的操作,因为它在主线程中执行,会影响主线程执行ui更新操作。

使用Message.callback回调

public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
从dispatchMessage定义可以看出,如果Message对象自带callback对象,handler不会执行handleMessage方法而是执行message.callback中定义的run方法,当然callback还是在handler关联的looper所绑定的线程中执行的。实际上Handler.post(Runnable r)方法就是把r添加到一个msg.callback的,也就是说,下面两种写法,没有什么区别:

1.使用Message.callback

[java] view plaincopyprint?
  1. Message msg = Message.obtain(myThreadHandler,new Runnable() {
  2. @Override
  3. public void run() {
  4. Log.d(Constant.TAG, MessageFormat.format("Thread[{0}]--myThreadHandler.Message.callback.run",
  5. Thread.currentThread().getName()));
  6. }
  7. });
  8. myThreadHandler.sendMessage(msg);

2.使用Handler.post

[java] view plaincopyprint?
  1. myThreadHandler.post(new Runnable() {
  2. @Override
  3. public void run() {
  4. Log.d(Constant.TAG, MessageFormat.format("Thread[{0}]--myThreadHandler.Message.callback.run",
  5. Thread.currentThread().getName()));
  6. }
  7. });

注:对于Handler机制相关测试,我写了一个测试类:

http://download.csdn.net/source/3275970

3.Handler对Activity finish影响。

在开发的过程中碰到一个棘手的问题,调用Activity.finish函数Acitivity没有执行生命周期的ondestory函数,后面查找半天是因为有一个handler成员,因为它有一个delay消息没有处理,调用Activity.finish,Activity不会马上destory,所以记得在Ativity finish前清理一下handle中的未处理的消息,这样Activity才会顺利的destory

 

0 0
原创粉丝点击