1.使用多线程时遇到的问题
2.我想和UI进行交互,但是每次都创建Runnable看起来很别扭,而且代码很难管理
3.我的程序中需要不断的加载更新的数据,我应该怎么确保数据的正确性?
4.用户快速 的点击按钮,我的程序无法有足够快的响应,应该怎么办?
二、什么是Handler及其作用(Handlder一定在主线程吗?)
Message
MessageQueue
looper
1)执行计划任务,你可以再预定的实现执行某些任务,可以模拟定时器
2)线程间通信。在Android的应用启动时,会创建一个主线程,主线程会创建一个消息队列来处理各种消息。当你创建子线程时,你可以在你的子线程中拿到父线程中创建的Handler对象,就可以通过该对象向父线程的消息队列发送消息了。由于Android要求在UI线程中更新界面,因此,可以通过该方法在其它线程中更新界面。
3)确保操作始终在某个特定的线程中运行。例如当我们从数据库加载数据时,除了程序启动时需要加载外,每当我们收到数据改变的通知时也需要重新加载。为了确保数据的有效性(始终使用最后一次查询时得到的数据),并减少不必要的查询操作,我们应当确保他们在同一个线程中运行。
角色描述
1.Looper(相当于隧道)一个线程可以产生一个Looper对象,由它来管理此线程里的Message Queue(车队,消息隧道)。
2.Handler:你可以构造Handler对象来与Looper沟通,以便Push新消息到Message Queue里,或者接收Looper(从Message Queue取出)所送来的消息。
3.Message Queue(消息队列):用来存放线程放入的消息。
4.线程:UI thread通常就是main thread,而Android启动程序时会替它建立一个Message Queue。
三、几个问题
1.多个Handler使用同一个HandlerThread
a.同一个HandlerThread中可以有多个Handler
b.同一个HandlerThread中使用多个Handler的Messsage不会混浴。
2.Handler可以创建到任意线程中吗?
a.在普通的Thread中不可以调用new Handler()创建并发送消息
b.在HandlerThread.onLooperPreapared()中可以调用new Handler创建并发送消息
3.如何指定Handler运行的线程
4.同一个Handler中不同的消息会同时执行吗?(不会,因为它是基于队列机制的)
a,定义两条有耗时操作的Message,并同时发送这两条消息。
b,现定义一个Runnable,尝试同时执行Message和Runnable。
5.当Handler正在运行的时候,调用removeMessage会有什么后果?
a.调用removeMessage一个还没有开始执行的Message,会直接移除掉这个未执行的Message
b.移除一个正在执行的message,这个message仍然会执行完。
总结:
1.Handler实例与消息处理是关联的,发送和接收要匹配。
2.只能依附在HandlerThread
3.可以通过设置Looper来选择其依赖的线程
4.所有操作都是在用一个线程中
5.removeMessage只能移除队列中的Message
四,代码
1.定义layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="@+id/button_handler1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="handler_laebl_1" />
<Button
android:id="@+id/button_handler2_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="handler_laebl_2.1" />
<Button
android:id="@+id/button_handler2_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="handler_laebl_2.2" />
<Button
android:id="@+id/button_handler3_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="handler_laebl_3.1" />
<Button
android:id="@+id/button_handler4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="handler_laebl_4" />
<Button
android:id="@+id/button_handler5_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="handler_laebl_5.1" />
<Button
android:id="@+id/button_handler5_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="handler_laebl_5.2_remove" />
</LinearLayout>
2.在java中使用Handler
package com.douzi.treaddemo;
import android.R.drawable;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Toast;
public class HandlerActivity extends Activity {
Handler mainHandler01;
Handler mainHandler02;
//定义一个HandlerThread
class SubHandlerThead extends HandlerThread{
public SubHandlerThead(String name){
super(name);
}
@Override
protected void onLooperPrepared() {
// TODO Auto-generated method stub
Looper looper = this.getLooper();
new Handler(looper){
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
Log.i("douzi", "在HandlerThread中获得消息:"+msg.getData().getString("key"));
}
}.sendMessage(difineNewMessage("label2.2"));
}
}
class DelayHandler extends Handler{
public DelayHandler(Looper looper){
super(looper);
}
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
Log.i("douzi", "开始消息:"+msg.getData().getString("key"));
try {
Thread.sleep(5* 1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.i("douzi", "结束消息:"+msg.getData().getString("key"));
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_handler);
mainHandler01 = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
Toast.makeText(HandlerActivity.this, "[主线程]Handler1获得消息:" + msg.getData().getString("key"), 3000)
.show();
}
};
mainHandler02 = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
Toast.makeText(HandlerActivity.this, "[主线程]Handler2获得消息:" + msg.getData().getString("key"), 3000)
.show();
}
};
//1.多个Handler使用同一个HandlerThread
//a.同一个HandlerThread中可以有多个Handler
//b.同一个HandlerThread中使用多个Handler的Messsage不会混浴。
findViewById(R.id.button_handler1).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
// mainHandler01.sendMessage(difineNewMessage("label"));
mainHandler02.sendMessage(difineNewMessage("label"));
}
}).start();
}
});
//在普通的Thread中不可以调用new Handler()创建并发送消息
findViewById(R.id.button_handler2_1).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
//在主线程中是可以执行的
//Handler handler = new Handler(Looper.getMainLooper());
//在普通线程不可以创建Handler
Handler handler = new Handler();
handler.sendMessage(difineNewMessage("label"));
}
}).start();
}
});
//在HandlerThread.onLooperPreapared()中可以调用new Handler创建并发送消息
findViewById(R.id.button_handler2_2).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
SubHandlerThead subHandlerThead = new SubHandlerThead("theadone");
subHandlerThead.start();
}
});
//在HandlerThread.onLooperPreapared()中可以调用new Handler创建并发送消息
findViewById(R.id.button_handler3_1).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
Handler handlerLable3 = new Handler(Looper.getMainLooper()){
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
Log.i("douzi", "获得消息:"+msg.getData().getString("key")+"在子线程中被处理。");
}
};
handlerLable3.sendMessage(difineNewMessage("label3"));
Looper.loop();
}
}).start();
}
});
//定义两条有耗时操作的Message,不会同时执行,会按先进先出的方式执行。
findViewById(R.id.button_handler4).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
HandlerThread labe4Thread = new HandlerThread("lab4_thread");
labe4Thread.start();
Handler lab4Handler = new DelayHandler(labe4Thread.getLooper());
lab4Handler.sendMessage(difineNewMessage("lab4 A"));
lab4Handler.sendMessage(difineNewMessage("lab4 B"));
}
});
HandlerThread lab5Thread = new HandlerThread("lab5_thread");
lab5Thread.start();
final Handler lab5Handler = new DelayHandler(lab5Thread.getLooper());
//
findViewById(R.id.button_handler5_1).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Message message = difineNewMessage("lab5");
message.what = 1;
lab5Handler.sendMessage(message);
}
});
findViewById(R.id.button_handler5_2).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
lab5Handler.removeMessages(1);
}
});
}
private Message difineNewMessage(String label) {
Message s = new Message();
Bundle bundle = new Bundle();
bundle.putString("key", label);
s.setData(bundle);
return s;
}
}