基本概念
Handler是Android提供的一套消息机制,可以在同一个或者不同线程之间传递消息。
在异步传递消息时,Handler像是两个线程之间通信的桥梁,桥的一端是Handler对象的setXxxMessage()方法(发送msg),另一端是同一个Handler对象的handleMessage(msg)方法(接收msg),两个线程共享一个Handler对象。
这个消息处理机制中,包含四个关键对象:Handler、Message、MessageQueue、Looper
Handler的作用
- 线程间通信
- 延时操作
- 定时循环
Handler的常用方法
public final boolean sendEmptyMessageDelayed(int what, long delayMillis)
(立即)发送一个延时 msg 到 handler 的消息队列中,等delayMillis毫秒之后,这个 msg 会被从消息队列中
取出,然后做一些处理。不管是否重写了 handleMessage 方法,delayMillis毫秒之后,这个 msg 都会被从消
息队列中取出。
public final boolean hasMessages(int what)
判断消息队列中是否包含标志为 what 的 msg
public final void removeMessages(int what)
移除消息队列中标志为 what 的 msg
public final void removeCallbacksAndMessages(@Nullable Object token)
如果 token 为 null,则清除当前 handler 对象中所有的 callback 和 msg
public final boolean postDelayed(@NonNull Runnable r, long delayMillis)
延时异步执行,这个Runnable在那个线程执行取决于Looper在哪个线程
使用场景:子线程要更新UI
Android为了线程安全,并不允许我们在UI线程(主线程)外操作UI,即不允许在子线程中直接操作UI,这时候就需要在子线程中调用Handler对象的setXxxMessage()方法(发送msg),在主线程中调用同一个Handler对象的handleMessage(msg)方法(接收msg),根据msg处理相应的跟新UI逻辑
错误示范:直接在子线程中更新UI
报错信息:Only the original thread that created a view hierarchy can touch its views.
package com.clc.app14;
import android.os.Bundle;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import java.util.Timer;
import java.util.TimerTask;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//执行Timer的schedule方法时,会新建一个线程
new Timer().schedule(new TimerTask() {
int i = 0;
@Override
public void run() {
i ++;
//在这个新的线程中操作UI
TextView textView = findViewById(R.id.textview);
textView.setText(""+i);
}
},0,1000);
}
}
利用Handler使子线程间接操作UI(通知主线程跟新UI)
package com.clc.app14;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import java.util.Timer;
import java.util.TimerTask;
public class MainActivity extends AppCompatActivity {
//系统已经为主线程初始化了一个Looper对象,所以我们直接创建Handler对象
Handler handler = new Handler(){
int i = 0;
//重写handleMessage(),接收本对象sendXxx()方法发来的msg对象,并做处理
@Override
public void handleMessage(Message msg) {
if (msg.what == 1){
i ++;
TextView textView = findViewById(R.id.textview);
textView.setText(""+i);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Timer().schedule(new TimerTask() {
@Override
public void run() {
//在需要的地方,调用在主线程中实例化的handler对象的sendXxx()方法,向本对象的handleMessage()发送msg
//每一次调用sendXxx(),执行一次handleMessage()
handler.sendEmptyMessage(1);
}
},0,1000);
}
}
另一个demo:自定义一个子线程
package com.clc.app14;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
Handler handler = new Handler() {
//重写handleMessage(),接收本对象sendXxx()方法发来的msg对象,并做处理
//handleMessage()在主线程中执行
//本对象sendXxx()方法的调用与执行,可以在其他线程中
@Override
public void handleMessage(Message msg) {
if (msg.what == 1){
TextView textView = findViewById(R.id.textview);
textView.setText(msg.getData().getString("key"));
}
}
};
//新建一个线程,在这个线程中通知更新UI
class Thread1 extends Thread{
@Override
public void run() {
//创建要发送的msg
Message msg = new Message();
msg.what = 1;
Bundle bundle = new Bundle();
bundle.putString("key","value");
msg.setData(bundle);
//在需要的地方,调用在子线程中实例化的handler对象的sendXxx()方法,向本对象的handleMessage()发送msg
//每一次调用sendXxx(),执行一次handleMessage()
handler.sendMessage(msg);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//在主线程中启动子线程
Thread1 thread1 = new Thread1();
thread1.start();
}
}
使用场景:定时循环
mHandler = new Handler();
mHandler.post(new Runnable() {
@Override
public void run() {
//TODO
mHandler.postDelayed(this, 1000);
}
});
使用场景:一定时间内多次回调,只执行第一次
package com.example.handler1;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private static final int DO_IT = 0;
private static final long DELAY_MILLIS = 1000;
private Handler mHandler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.tv).setOnClickListener(v -> {
if (!mHandler.hasMessages(DO_IT)) {
Log.d(TAG, "do it");
mHandler.sendEmptyMessageDelayed(DO_IT, DELAY_MILLIS);
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
mHandler.removeCallbacksAndMessages(null);
}
}
使用场景:多次快速连续回调,只执行最后一次
package com.example.handler1;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private static final int DO_IT = 0;
private static final long DELAY_MILLIS = 1000;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(@NonNull Message msg) {
if (msg.what == DO_IT) {
Log.d(TAG, "do it");
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.tv).setOnClickListener(v -> {
if (mHandler.hasMessages(DO_IT)) {
mHandler.removeMessages(DO_IT);
}
mHandler.sendEmptyMessageDelayed(DO_IT, DELAY_MILLIS);
});
}
@Override
protected void onDestroy() {
super.onDestroy();
mHandler.removeCallbacksAndMessages(null);
}
}