Android中的Looper、Handler与HandlerThread

Looper:

    Looper类用来管理特定线程内对象之间的消息交换(Message Exchange)。你的应用程序可以产生许多个线程。而一个线程可以有许多个组件,这些组件之间常常需要互相交换讯息。如果有这种需要,您可以替线程构造一个Looper对象,来担任讯息交换的管理工作。Looper对象会建立一个MessageQueue数据结构来存放各对象传来的消息(包括UI事件或System事件等)。每一个线程里可含有一个Looper对象以及一个MessageQueue数据结构。在你的应用程序里,可以定义Handler的子类别来接收Looper所送出的消息。

Handler:

    Handler的最主要的作用就是,把消息发送到与此Handler绑定的线程的MessageQueue上,因此在构建Handler时必须指定一个Looper对象,如果不指定则通过Looper获取调用者线程的Looper对象。Handler会关联一个单独的线程和消息队列,也就是是在该关联的线程中执行handleMessage()操作。Handler默认关联主线程,。虽然要提供Runnable参数 ,但默认是直接调用Runnable中的run()方法。也就是默认下会在主线程执行,如果在这里面的操作会有阻塞,界面也会卡住。如果要在其他线程执行,可以使用HandlerThread。

Handler的constructor
/**
 * Default constructor associates this handler with the queue for the
 * current thread. If there isn't one, this handler won't be able to receive messages.
 */
public Handler() {
    if (FIND_POTENTIAL_LEAKS) {
     final Class<? extends Handler> klass = getClass();
      if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
          (klass.getModifiers() & Modifier.STATIC) == 0) {
        Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
           klass.getCanonicalName());
            }
      }

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

Default constructor 使用Looper.myLooper初始化mLooper;

另外的几个constructor如下:

public Handler(Callback callback) ;
/*使用指定的looper初始化,不写则默认为主线程的Looper*/
public Handler(Looper looper) {         
mLooper = looper;
    mQueue = looper.mQueue;
    mCallback = null;
}
public Handler(Looper looper, Callback callback) {
        mLooper = looper;
        mQueue = looper.mQueue;
        mCallback = callback;
}

Handler会关联一个单独的线程和消息队列,也就是是在该关联的线程中执行handleMessage()操作。Handler默认关联主线程,。虽然要提供Runnable参数 ,但默认是直接调用Runnable中的run()方法。也就是默认下会在主线程执行,如果在这里面的操作会有阻塞,界面也会卡住。如果要在其他线程执行,可以使用HandlerThread。

HandlerThread

final HandlerThread handlerThread = new HandlerThread("handlerThread");
handlerThread.start();  //启动一个新的线程
/*MyHandler为自定义类,继承Handler,重写handleMessage方法*/
final MyHandler handler = new MyHandler(thread.getLooper());  

    class MyHandler extends Handler {
        public MyHandler(Looper looper) {
            super(looper);
        }
        @Override
        public void handleMessage(Message msg) {  
            Log.i(TAG, "==================" + Thread.currentThread().getName());
            super.handleMessage(msg);
        }
    }

还有第二种用法:

HandlerThread uIhandlerThread = new HandlerThread("update");
 uIhandlerThread.start();

//new一个匿名的类,实现了handleMessage方法,
 Handler uIhandler = new Handler(uIhandlerThread.getLooper(),new Handler.Callback() {
    public boolean handleMessage(Message msg) {
        Bundle b = msg.getData();  
        int age = b.getInt("age");  
        String name = b.getString("name");  
        System.out.println("age is " + age + ", name is" + name);  
        System.out.println("Handler--->" + Thread.currentThread().getId());  
        System.out.println("handlerMessage");  
        return true;  
     }
});

下面通过一个简单的例子,来分别分析一下如何使用它们。

需求:在界面上显示10000以内的所有质数。

方法一:

package com.example.handlerandlooperdemos;

import java.util.ArrayList;
import java.util.List;

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class HandlerAndLooperDemos extends Activity {
	private final static String TAG = "yxf";
	private final static String UPPER_NUM = "upper_num";
	private final static int MSG_CAL_PRIME = 001;
	private final static int MSG_UPDATE_UI = 002;
	
	private CaculateThread mThread;
	private Button mButton;
	private TextView mResult;
	private List<Integer> mResultPrimer = new ArrayList<Integer>();
	private Handler mMainHandler;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		mThread = new CaculateThread();
		mThread.start();
		mResult = (TextView) findViewById(R.id.result);
		mButton = (Button) findViewById(R.id.caculate_button);
		mButton.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				caculatePrimer();
			}
		});
		
		mMainHandler = new Handler(){
			@Override
			public void handleMessage(Message msg) {
				// TODO Auto-generated method stub
				switch(msg.what){
				case MSG_UPDATE_UI:
					mResult.setText(mResultPrimer.toString());
					break;
				default:
					break;
				}
			}
		};
	}

	private void caculatePrimer(){
		Message msg = new Message();
		msg.what = MSG_CAL_PRIME;
		Bundle bundle = new Bundle();
		bundle.putInt(UPPER_NUM, 10000);
		msg.setData(bundle);
		mThread.threadHandler.sendMessage(msg);
	}
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}
	
	/**
	 *一个自定义的Thread,它的成员对象threadHandler在本线程中执行处理message的行为。
	 */
	public class CaculateThread extends Thread {
		public Handler threadHandler;
		@Override
		public void run() {
			// TODO Auto-generated method stub
			//使现有的Thread含有一个Looper对象。
			Looper.prepare();
			threadHandler = new Handler(){
				@Override
				public void handleMessage(Message msg) {
					// TODO Auto-generated method stub
					if(msg.what == MSG_CAL_PRIME){
						int upper = msg.getData().getInt(UPPER_NUM);
						List<Integer> nums = new ArrayList<Integer>();
						outer:
						for(int i = 2; i <= upper;i++){
							for(int j = 2; j < Math.sqrt(i); j++){
								if(i != 2 && i % j == 0){
									continue outer;
								}
							}
							nums.add(i);
						}
						mResultPrimer = nums;
						//Toast.makeText(MainActivity.this, nums.toString(), Toast.LENGTH_LONG).show();
						//这里需要更新UI,因此调用主线程的Handler来处理更新UI的任务。
						mMainHandler.sendMessage(Message.obtain(mMainHandler,MSG_UPDATE_UI));
					}
				}
			};
			Looper.loop();
		}
	}
}
res/layout/activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:orientation="vertical"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent">
   
   <TextView 
       android:id="@android:id/empty"
       android:layout_width="fill_parent" 
       android:layout_height="wrap_content"
       android:text="Caculate prime:" 
       android:textSize="18sp" />
   
   <TextView 
       android:id="@+id/result"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_weight="1"
       />
   <Button
       android:id="@+id/caculate_button"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="Start" 
    />

</LinearLayout> 

方法二:

package com.example.handlerthreaddemos;

import java.util.ArrayList;
import java.util.List;

import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;

public class HandleThreadDemos extends Activity {
	private static final String TAG = "yxf";
	private static final int MSG_CAL_PRIME = 001;
	private static final int MSG_UPDATE_UI = 002;
	private final static String UPPER_NUM = "upper_num";
	private int count = 0;
	private Button mButton;
	private TextView mResult;
	private Handler mThreadHandler ; 
	private Handler mMainHandler;
	private List<Integer> mResultPrimer = new ArrayList<Integer>();
	/*
	private Runnable mRunnable = new Runnable() {     
	    public void run() {     
	        //为了方便 查看,我们用Log打印出来     
	        Log.e(TAG, "Runnable Thread: " + Thread.currentThread().getId() + " " +count);     
	        count++;
	        //如果不注释掉setTitle()会报错,只有主线程才可以修改UI.
	        //setTitle("" +count);     
	        //每2秒执行一次     
	        mThreadHandler.postDelayed(mRunnable, 2000);     
	    }     
	};
	*/     
	@Override     
	public void onCreate(Bundle savedInstanceState) {     
	    Log.e(TAG, "Main Thread: "+Thread.currentThread().getId() + " " +count);     
	    super.onCreate(savedInstanceState);     
	    setContentView(R.layout.activity_main);      
	    //通过Handler启动线程     
	    HandlerThread handlerThread = new HandlerThread("threadone");   
	    handlerThread.start();
	    mResult = (TextView) findViewById(R.id.result);
		mButton = (Button) findViewById(R.id.caculate_button);
		mButton.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				Message msg = new Message();
				msg.what = MSG_CAL_PRIME;
				Bundle bundle = new Bundle();
				bundle.putInt(UPPER_NUM, 10000);
				msg.setData(bundle);
				mThreadHandler.sendMessage(msg);
			}
		});
	    //mThreadHandler用handlThread的looper初始化,表示该handler是handlerThread线程下的handler,而不是主线程的handler.
	    //Handler对象的Looper对象是属于哪个线程的,就表示消息由那个线程来处理。
	    mThreadHandler =  new Handler(handlerThread.getLooper()){
			@Override
			public void handleMessage(Message msg) {
				// TODO Auto-generated method stub
				if(msg.what == MSG_CAL_PRIME){
					int upper = msg.getData().getInt(UPPER_NUM);
					List<Integer> nums = new ArrayList<Integer>();
					outer:
					for(int i = 2; i <= upper;i++){
						for(int j = 2; j < Math.sqrt(i); j++){
							if(i != 2 && i % j == 0){
								continue outer;
							}
						}
						nums.add(i);
					 }
					 mResultPrimer = nums;
					 //Toast.makeText(MainActivity.this, nums.toString(), Toast.LENGTH_LONG).show();
					 //这里需要更新UI,因此调用主线程的Handler来处理更新UI的任务。
					 mMainHandler.sendMessage(Message.obtain(mMainHandler,MSG_UPDATE_UI));
			    }   
			}
	    };
	    mMainHandler = new Handler(){
			@Override
			public void handleMessage(Message msg) {
				// TODO Auto-generated method stub
				switch(msg.what){
				case MSG_UPDATE_UI:
					mResult.setText(mResultPrimer.toString());
					break;
				default:
					break;
				}
			}
	    	
	    };
	    mThreadHandler.sendMessage(Message.obtain(mThreadHandler, MSG_UPDATE_UI));     
	}     
	
	@Override     
	protected void onDestroy() {     
	    //将线程与当前handler解除   
	    //mThreadHandler.removeCallbacks(mRunnable);     
	    super.onDestroy();     
	}     
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值