前言:
? ? ? ? 之前写过一篇博客,大概的讲了一下自己手写Handler的一些总结和重要代码,但是总觉得有所欠缺,除了自己能看懂,别人都看不明白写了些啥,所以,决定重写写一次,从Handler的用法开始。
Handler学习笔记
什么是Handler?
? ? ? ? 用于处理异步消息的工具。工作线程通过Handler发送消息到消息队列MessageQueue,Looper会去轮询MessageQueue消息队列,取出Message,然后交给Handler分发消息,处理消息。
为什么要用Handler?
? ? ? ? Android中,规定只有主线程能操作UI,那么对于异步处理UI的情况,就需要使用主线程的Handler来进行处理子线程发送的消息。
Handler的用法?
1.Handler.sendMessage(),
? ? 根据创建Handler方式的不同有两种写法,一种是新建Handler子类继承自Handler重写HandleMessage(Message msg)方法对消息进行处理,另一种是匿名内部类方式重写HandleMessage(Message?msg)方法对消息进行处理
? ? ? ? UI布局
<?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">
<TextView
android:id="@+id/tv_handler_1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:gravity="center"
android:textSize="20sp"
/>
</LinearLayout>
? ? ? ? 1)新建Handler子类方式
package com.example.handlertest3;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private Handler handler;
//TextView控件
private TextView tvHandler;
//新建子类Handler继承Handler,重写handleMessage(Message msg)方法处理消息
class MHandler extends Handler{
@Override
public void handleMessage(@NonNull Message msg) {
switch (msg.what){
case 1:
tvHandler.setText(msg.obj.toString());
break;
case 2:
tvHandler.setText(msg.obj.toString());
break;
default:
break;
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//找到TextView控件
tvHandler = findViewById(R.id.tv_handler_1);
//top1 在主线程创建Handler实例
handler = new MHandler();
//top2 new Thread方式创建子线程1,发送message消息到消息队列,并且指定操作的UI内容
new Thread(){
//重写run()方法,在run()方法里面实现要实现的逻辑功能
@Override
public void run() {
try {
//子线程休眠3秒
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//实例化消息对象
Message msg = Message.obtain();
//消息标识
msg.what = 1;
//消息内容
msg.obj = "执行了子线程1的UI操作";
//发送消息到消息队列MessageQueue
handler.sendMessage(msg);
}
}.start();
//new Runnable方式创建子线程
new Thread(new Runnable() {
@Override
public void run() {
try {
//线程休眠3秒
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//实例化消息对象
Message msg = Message.obtain();
//消息标识
msg.what = 2;
//消息内容
msg.obj = "执行了线程2的UI操作";
//发送消息到消息队列MessageQueue
handler.sendMessage(msg);
}
}).start();
}
}
? ? ? ? 2)匿名内部类方式
package com.example.handlertest3;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private Handler handler;
//TextView控件
private TextView tvHandler;
/* //新建子类Handler继承Handler,重写handleMessage(Message msg)方法处理消息
class MHandler extends Handler{
@Override
public void handleMessage(@NonNull Message msg) {
switch (msg.what){
case 1:
tvHandler.setText(msg.obj.toString());
break;
case 2:
tvHandler.setText(msg.obj.toString());
break;
default:
break;
}
}
}*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//找到TextView控件
tvHandler = findViewById(R.id.tv_handler_1);
//top1 在主线程创建Handler实例
/*handler = new MHandler();*/
//通过匿名内部类方式创建Handler实例并重写handlMessage(Message msg)方法处理消息
handler = new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
switch (msg.what){
case 1:
tvHandler.setText(msg.obj.toString());
break;
case 2:
tvHandler.setText(msg.obj.toString());
break;
}
}
};
//top2 new Thread方式创建子线程1,发送message消息到消息队列,并且指定操作的UI内容
new Thread(){
//重写run()方法,在run()方法里面实现要实现的逻辑功能
@Override
public void run() {
try {
//子线程休眠3秒
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//实例化消息对象
Message msg = Message.obtain();
//消息标识
msg.what = 1;
//消息内容
msg.obj = "执行了子线程1的UI操作";
//发送消息到消息队列MessageQueue
handler.sendMessage(msg);
}
}.start();
//new Runnable方式创建子线程
new Thread(new Runnable() {
@Override
public void run() {
try {
//线程休眠3秒
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//实例化消息对象
Message msg = Message.obtain();
//消息标识
msg.what = 2;
//消息内容
msg.obj = "执行了线程2的UI操作";
//发送消息到消息队列MessageQueue
handler.sendMessage(msg);
}
}).start();
}
}
2.Handler.postMessage()
package com.example.testhandlerpost;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private TextView tvPostHandler;
private Handler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//找到TextView控件
tvPostHandler = findViewById(R.id.tv_post_handler);
//在主线程创建Handler实例
mHandler = new Handler();
new Thread(){
@Override
public void run() {
try {
//线程1休眠3秒
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//通过Handler.Post()发送消息到消息队列,需要一个Runnable对象
mHandler.post(new Runnable() {
@Override
public void run() {
tvPostHandler.setText("执行了线程1的UI操作");
}
});
}
}.start();
new Thread(new Runnable() {
@Override
public void run() {
try {
//线程2休眠6秒
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
mHandler.post(new Runnable() {
@Override
public void run() {
tvPostHandler.setText("执行了线程2的UI操作");
}
});
}
}).start();
}
}
Handler的基本原理
? ? ? ? 1.创建主线程的时候,会自动调用ActivityThread.java类中的main()方法,在main()方法中,调用了Looper.prepareMainLooper()生成一个Looper对象,同时生成一个MessageQueue对象。同时在ActivityThread中开启了Loop.loop消息循环。
#ActivityThread.java
public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
// Install selective syscall interception
AndroidOs.install();
// CloseGuard defaults to true and can be quite spammy. We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
// Make sure TrustedCertificateStore looks in the right place for CA certificates
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
// Call per-process mainline module initialization.
initializeMainlineModules();
Process.setArgV0("<pre-initialized>");
//创建主线程的时候生成Looper对象同时生成了MessageQueue对象
Looper.prepareMainLooper();
// Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
// It will be in the format "seq=114"
long startSeq = 0;
if (args != null) {
for (int i = args.length - 1; i >= 0; --i) {
if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
startSeq = Long.parseLong(
args[i].substring(PROC_START_SEQ_IDENT.length()));
}
}
}
ActivityThread thread = new ActivityThread();//-------创建主线程-------------!!!!
thread.attach(false, startSeq);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Looper.loop();//------------------自动开启消息循环--------------------------!!!
throw new RuntimeException("Main thread loop unexpectedly exited");
}
#Looper.prepareMainLooper()
@Deprecated
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
#Looper.prepare(boolean quitAllowed)
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
#Loopr.Looper(boolean quitAllowed)构造方法,在创建Looper对象的同时,也生成了MessageQueue对象
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
/**
* 获取当前线程的Looper对象,如果调用线程没有与Looper进行关联,那么返回null
*/
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
我们在使用的时候,会在主线程创建一个Handler对象,重写handleMessage(Message?msg)方法对Looper.loop在MessageQueue消息队列轮询取出的消息进行分发,处理。
@Deprecated
public Handler() {
this(null, false);
}
public Handler(@Nullable Callback callback, boolean async) {
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());
}
}
//获取当前线程的Looper对象
//如果当前线程的Looper对象为空,抛出异常
//所以如果需要在子线程创建Handler对象,需要先创建Looper对象
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
//绑定MessageQueue对象到当前线程的Looper对象上
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
|