Handler的使用
子线程与主线程通信更新UI
//构建handlering重写handleMessage方法(内存泄漏的解决参见后文)
Handler handler = new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
switch (msg.what){
case 1001:{
progressBar.setProgress(msg.arg1);
break;
}
}
}
};
//子线程
new Thread(new Runnable() {
@Override
public void run() {
int pro = 0;
for (int i = 0; i < 10; i++) {
pro += 10;
Message message = Message.obtain();
message.what = 1001;
message.arg1 = pro;
handler.sendMessage(message);
}
}
}).start();
主线程改变子线程执行状态:通过自定义Runnable实现
//实现Runnable接口
class MyRunnable implements Runnable{
public boolean isRunning = true;
@Override
public void run() {
int pro = 0;
for (int i = 0; i < 10 && isRunning; i++) {
pro += 10;
Message message = Message.obtain();
message.what = 1001;
message.arg1 = pro;
try {
Thread.sleep(1000);
handler.sendMessage(message);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//添加主线程停止子线程执行按钮监听
MyRunnable runnable = new MyRunnable();
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
runnable.isRunning = false;
}
});
Thread thread = new Thread(runnable);
thread.start();
创建子线程的handler(不常用)
//自行实现Thread类
class MyThread extends Thread{
Looper looper;
public Boolean isRunning = true;//通过设置此标志来终止线程
//防止出现空指针:必须保证looper不空
//HandlerThread也是这么实现的
@Override
public void run() {
super.run();
Looper.prepare();
synchronized (this){
looper = Looper.myLooper();
notifyAll();
}
Looper.loop();
}
public Looper getLooper(){
if(!isAlive()){
return null;
}
synchronized (this){
while (isAlive() && looper == null){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
return looper;
}
public void quit(){
Looper looper = getLooper();
if (looper != null) {
looper.quit();
}
isRunning = false;
}
}
//使用
MyThread myThread = new MyThread();
myThread.start();
Handler workHandler = new Handler(myThread.getLooper()){
@Override
public void handleMessage(@NonNull Message msg) {
//进行子线程消息处理:此处执行的代码都是在子线程中执行的
//可以通过此方式拿到子线程的handler并开启一个耗时任务
//不能通过向子线程的MessageQueue发送消息来停止子线程
//因为此时的子线程的消息循环已经被阻塞了,是处理不了其他消息的
//可以在主线程中,通过设置isRunning的标志,来使线程停止
}
};
HandlerThread的使用
HandlerThread workThread = new HandlerThread("workThread");
workThread.start();
workHanlder = new Handler(workThread.getLooper()){
@Override
public void handleMessage(@NonNull Message msg) {
//可以在这启动一个耗时操作,正如上面所说,
//只能通过主线程改变该线程的标志来使它停止
}
};
workHanlder.sendEmptyMessage(100);//向子线程的消息循环发送消息
Handler内存泄漏解决
非静态内部类会默认持有外部类的强引用,且handler中往往执行子线程的耗时操作,所以在Activity销毁时,因为handler中持有Activity的引用,所以会发生内存泄漏,为保险起见,我们会同时实现下面这两种方法。
通过设置静态内部类或者外部类(以下只显示静态内部类)
//静态内部类的定义
static class MyHandler extends Handler{
private WeakReference<MainActivity> weakReference;
private TextView textView;
public MyHandler(MainActivity mainActivity){
weakReference = new WeakReference<>(mainActivity);
}
@Override
public void handleMessage(@NonNull Message msg) {
switch (msg.what){
case 1001:{
MainActivity activity = weakReference.get();
if (activity != null) {
textView = activity.textView;
textView.setText("修改自静态内部类");
}
break;
}
}
}
}
//使用
Handler handler = new MyHandler(this);
handler.sendEmptyMessage(1001);
通过在Activity销毁时清空消息循环
@Override
protected void onDestroy() {
super.onDestroy();
handler.removeCallbacksAndMessages(null);
}