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();
}
}