HandlerThread使用教程(一)

一般情况下,无论是否使用了后台线程,handler的处理实际就是UI主线程的处理,一般的使用方式为我们通过后台线程执行某些操作,如果需要进行ui互动,将消息发送到handler的队列中,然后在ui主线程中进行处理。这是我们通常用的情况。

之前我们讨论过Ui归ui,处理归处理。然而可能有这样的请求,举个例子,在某些情况下,handler收到消息触发的处理中可能会有说了sleep()这样导致main线程进入sleep()状态,不是我们期待的。因此我们希望通过一个线程专门处理handler的消息,这个线程也是依次从handler的队列中获取信息,逐个进行处理,保证按去哪,不会出现混乱引发异常。

针对此android提供了HandlerThread。方式使用方法如下:

//步骤1:创建HandlerThread的一个对象,并开启这个线程,handlerthread将通过looper来处理handler对列中的消息,也就是如果发现Handler中有消息,将在HandlerThread这个线程中进行处理。

HandlerThread ht =new HandlerThread (“handler_thread”);

//步骤2 :启动handlerthread这个线程

ht.start();

//步骤3:创建handler时,带上looper参数,即handlerThread.getLooper()。注意必须在handlerThread启动后才能调用,否则会出错,getLooper()会返回null,则程序异常出错

Handler handler=new Handler (ht.getLooper()){

…..

public void handleMessage(Message msg){

…../这里的处理,将不在主线程中执行,而在handlerthread线程中执行,可以通过Thread.currentThread().getId()或者Thread.currentThread().getName()来确定/
}
};

示例:

界面中只有一个button,点击button后会在HandlerThread中执行一个耗时操作。本程序主要观察handler的handleMessage()方法是在哪个线程中执行的。

“`
package com.example.handler03;

import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {
private Button button;
private TextView textview ;
public static final int PARAM=1;
HandlerThread ht=new HandlerThread(“handler_thread”);

/*
 * 此处的Runnable对象用于判断所执行程序位于哪个线程,可调用runOnUiThread(runAction)方法判断
 * 调用该方法实际上就是执行的Runnable对象的run方法
 */
Runnable runAction=new Runnable(){

    @Override
    public void run() {
        // TODO Auto-generated method stub
        Log.d("当前线程","------>"+Thread.currentThread().getName());
        Toast.makeText(getApplicationContext(),"执行所在线程" , Toast.LENGTH_LONG);
    }

};


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.fragment_main);
    button=(Button)findViewById(R.id.buttonId);
    textview=(TextView)findViewById(R.id.textViewId);

    //handlerThread线程必须要在创建handler之前执行,因为创建
    //handler时要用到HandlerThread对象的looper对象
    ht.start();



 //获取ht线程所对应的looper对象,问题是这个looper对象是怎样得到的?
    final Handler handler=new Handler(ht.getLooper()){
        @Override
        public void handleMessage(Message msg) {
            // TODO Auto-generated method stub
        super.handleMessage(msg);
            for(int i=0;i<=2;i++){
                try {
                    //按照传统做法当在子线程调用sendMessage时,
                    //在主线程中的handleMessage会执行,但是主线程不能进行网络访问(网络不稳定),也不能进行耗时比较长的操作
                    //而现在的handleMessage操作是在子线程HandlerThread线程中进行的,所以不会引发ANR异常
                    Thread.sleep(2000);//模仿耗时操作
                    //一下两句话都是输出当前线程
                    Log.d("当前线程","------>"+Thread.currentThread().getName());
                    runOnUiThread(runAction);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }

    };

button.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View v) {
    // TODO Auto-generated method stub
    switch(v.getId()){
    case R.id.buttonId:
        new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                //Looper.prepare();
                Message msg=handler.obtainMessage();

                handler.sendMessage(msg);
                Log.d("OnClick","sendMessage WorkerThread--------->"+Thread.currentThread().getName());
                //Looper.loop();

            }
        }).start();

    break;
    default:
        break;

    }

}

});

}

}

查看程序的日志输出

03-06 21:32:00.918: D/OnClick(28927): sendMessage WorkerThread———>Thread-22280

03-06 21:32:02.919: D/当前线程(28927): ——>handler_thread

03-06 21:32:02.919: D/当前线程(28927): ——>main

03-06 21:32:04.920: D/当前线程(28927): ——>handler_thread

03-06 21:32:04.920: D/当前线程(28927): ——>main
03-06 21:32:06.920: D/当前线程(28927): ——>handler_thread

03-06 21:32:06.920: D/当前线程(28927): ——>main
从日志输出可知与文章最初叙述相符

你可能感兴趣的:(教程,消息发送,HandlerThr)