MessageQueue
消息队列,存放消息的地方.每个线程只能拥有一个MessageQueue
Looper
Adnroid系统中的Looper负责管理线程的MessageQueue.除了主线程外,创建的线程默认是没有Looper和MessageQueue,创建一个Looper会同时创建一个MessageQueue,可以使用Looper.prepare()创建MessageQueue,Looper.loop()进入消息循环,Looper.release()释放资源.
class LooperThread extends Thread {
public Handler mHandler;
@Override
public void run() {
// 创建消息队列
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
// process incoming messages here
}
};
// 进入消息循环
Looper.loop();
super.run();
//释放资源,使用Looper.release方法。
}
}
Message
消息对象,MessageQueue里存放的对象,可以调用removeMessages()时,将Message从Message Queue中删除和通过Handler对象的obtainMessage()获取一个Message实例,可以在线程中使用Handler对象的sendEmptyMessage()或者sendMessage()来传递Bundle对象到Handler,对Handler类提供handlerMessage(Message msg)判断,通过msg.what来区分每一条信息
Handler
Handler的作用是把消息加入特定的Looper消息队列中,并分发和处理该消息队列中的消息.如另一个线程怎样把消息放入主(UI)线程的消息队列,可以通过Handler对象,通过调用Handler主线程的sendMessage接口,把消息队列放入主线程的消息队列,并在该Handler的handleMessage()来处理消息
下面是模拟多线程并发的例子其中有用到当所有线程执行完毕更新UI需要Handler
/** Called when the activity is first created. */
private String URL = "http://www.baidu.com";
private int NUM = 100;
private Button myButton;
private EditText mEditTextURL, mEditTextNUM;
private ProgressDialog pd;
private static int count = 0;
Handler myHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
if (msg.what == 0)
pd.dismiss();
super.handleMessage(msg);
};
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mEditTextURL = (EditText) findViewById(R.id.myEditTextURL);
mEditTextNUM = (EditText) findViewById(R.id.myEditTextNUM);
myButton = (Button) findViewById(R.id.myButton);
myButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (!mEditTextURL.getText().toString().trim().equals(""))
URL = mEditTextURL.getText().toString().trim();
if (!mEditTextNUM.getText().toString().trim().equals(""))
NUM = Integer.parseInt(mEditTextNUM.getText().toString()
.trim());
pd = ProgressDialog.show(HttpTestActivity.this, "xxx","xxx...");
outFile();
for (int i = 0; i < NUM; i++) {
count++;
new Thread(new Handl(i)).start();
}
}
});
}
public void outFile() {
PrintStream stream = null;
try {
File f = new File(Environment.getExternalStorageDirectory(),
"xxx.txt");
if (!f.exists())
f.createNewFile();
stream = new PrintStream(f);
System.setOut(stream);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
class Handl implements Runnable {
private int No;
public Handl(int no) {
this.No = no;
}
@Override
public void run() {
// TODO Auto-generated method stub
Thread.currentThread().setName(No + "");
HttpClient httpClient = new DefaultHttpClient();
// 设置请求超时
httpClient.getParams().setParameter(
CoreConnectionPNames.CONNECTION_TIMEOUT, 5000);
// 设置读取超时
httpClient.getParams().setParameter(
CoreConnectionPNames.SO_TIMEOUT, 3000);
HttpGet get = new HttpGet(URL);
String strResult = "";
try {
HttpResponse response = httpClient.execute(get);
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
strResult = EntityUtils.toString(response.getEntity());
System.out.println("ThreadID:"
+ Thread.currentThread().getName());
System.out.println(strResult);
} else {
System.out.println(Thread.currentThread().getName()
+ "请求失败");
}
Thread.sleep((long) Math.random() * 1000);
} catch (InterruptedException e) {
// TODO: handle exception
e.printStackTrace();
} catch (IOException e) {
// TODO: handle exception
e.printStackTrace();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
} finally {
synchronized (this) {
count--;
}
}
Message message = new Message();
message.what = count;
myHandler.sendMessage(message);
}
消息的处理者,handler负责将需要传递的信息封装成Message,通过调用handler对象的obtainMessage()来实现; 将消息传递给Looper,这是通过handler对象的sendMessage()来实现的。继而由Looper将Message放入MessageQueue中。 当Looper对象看到MessageQueue中含有Message,就将其广播出去。该handler对象收到该消息后,调用相应的handler对象的handleMessage()方法 对其进行处理。
更多参考: