https://blog.youkuaiyun.com/carson_ho/article/details/80305411
1. 基本简介:
1.在新启动的线程中发送消息
2.在主线程中获取,并处理消息
--那在新启动的线程何时发送消息?主线程何时去获取并处理消息?
2. 主要概念:
- Handler:快递员(属于某个快递公司的职员)
--把Message发给Looper管理的MessageQueue,并负责处理Looper对象分给它的消息。
- Message:包裹(可以放置很多东西的箱子)
- MessageQueue:快递分拣中心(分拣快递的传送带)
--由Looper负责管理,采用先进先出的方式。
- Looper:快递公司(具有处理包裹去向的管理中心)
--每个线程只有一个Looper,负责管理MessageQueue,会不断地从MessageQueue中取出消息,并将消息分给对应的Handler处理。
3. 大致理解:
- 某时,你想刷新主界面的TextView,无奈你不在主线程,此时你就会包装好Message,然后声明一个Handler,让Handler将你的Message送往主线程(Looper),Handler将你的Message送到Looper后,还需要排队等待,等轮到你的时候,主线程Looper就会告诉Handler,这个Message可以处理了,你负责分发一下,于是,Handler将该Message分发到相应的回调或者handleMessage( ) 方法中,于是,你就在该方法中更新了UI。

4. 主要作用:
- 使用
Handler的原因:将工作线程需操作UI的消息 传递 到主线程,使得主线程可根据工作线程的需求 更新UI,从而避免线程操作不安全的问题 - 具体描述如下

5. 大致总结
(1)主线程可以直接创建Handler对象,主线程默认自动初始化Looper。
(2)子线程中需要先调用Looper.prepare()才能创建Handler对象,否则运行抛出”Can’t create handler inside thread that has not called Looper.prepare()”异常信息。
子线程向主线程传值:
public class MainActivity extends AppCompatActivity {
private Handler mHandler;//将mHandler指定轮询的Looper
@SuppressLint("HandlerLeak")
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 0:
//do something,refresh UI;
Log.d("当前子线程是----->",Thread.currentThread()+""+msg.obj);
break;
default:
break;
}
}
};
new Thread() {
public void run() {
Message message = new Message();
message.obj = "子线程发送的消息Hi~Hi";
mHandler.sendMessage(message);
};
}.start();
}
}

主线程向子线程发送消息:需要在子线程里初始化Looper,并在主线程里创建的Handler引用子线程的Looper(Handler中引用的是哪个线程的Looper,就在哪个线程里处理消息),下面看代码:
HandlerThread继承于Thread,所以它本质就是个Thread,只不过在内部直接实现了Looper的实现,不需要手动去调用Looper.prepare()和Looper.loop()这些方法。有了自己的looper,可以在自己的线程中分发和处理消息。start后可以获得其Looper对象,并且使用这个Looper对象实例Handler,之后Handler就可以运行在其他线程中了。
import androidx.appcompat.app.AppCompatActivity;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.util.Log;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private MyThread thread;
//创建子线程
class MyThread extends Thread{
private Looper looper;//取出该子线程的Looper
public void run() {
Looper.prepare();//创建该子线程的Looper
looper = Looper.myLooper();//取出该子线程的Looper
Looper.loop();//只要调用了该方法才能不断循环取出消息
}
}
private Handler mHandler;//将mHandler指定轮询的Looper
@SuppressLint("HandlerLeak")
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView tv = new TextView(this);
tv.setText("Handler实验");
setContentView(tv);
//实例化一个特殊的线程HandlerThread,必须给其指定一个名字
HandlerThread thread = new HandlerThread("handler thread");
thread.start();//千万不要忘记开启这个线程
//将mHandler与thread相关联
mHandler = new Handler(thread.getLooper()){
public void handleMessage(android.os.Message msg) {
Log.d("当前子线程是----->", Thread.currentThread()+"");
};
};
mHandler.sendEmptyMessage(1);//发送消息
}
}

子线程向子线程发消息:
private Handler mHandler;//将mHandler指定轮询的Looper
@SuppressLint("HandlerLeak")
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Thread1 thread1= new Thread1();
Thread2 thread2 = new Thread2();
new Thread(thread1).start();
if(thread1.getHandler() == null) {
try {
Thread.sleep(1000);
mHandler = thread1.getHandler();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
new Thread(thread2).start();
}
private Handler handler;
//子线程一
class Thread1 implements Runnable{
private Handler mHandler;
//run运行后才不为null在main里判断
public Handler getHandler(){
return mHandler;
}
@SuppressLint("HandlerLeak")
@Override
public void run() {
Looper.prepare();
mHandler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case 1:
Log.d("线程A","线程B发过来消息了--"+msg.obj);
break;
}
}
};
Looper.loop();
}
}
//子线程二
class Thread2 implements Runnable{
@Override
public void run() {
Message mess= Message.obtain();
mess.what=1;
mess.obj= "线程B"+System.currentTimeMillis();
mHandler.sendMessage(mess);
}
}

子线程使用Handler的步骤:https://blog.youkuaiyun.com/qq_41673194/article/details/80022875
(3)每个线程中最多只能有一个Looper对象,否则抛出异常;
一个Looper只能对应了一个MessageQueue。
一个MessageQueue可以对应多个Handler。
(4)可以通过Looper.myLooper()获取当前线程的Looper实例,通过Looper.getMainLooper()获取主(UI)线程的Looper实例。
(5)Handler的post方法将一个 Runnable 投递到 Handler 内部的 Looper中去处理,
post(Runnable)
postAtTime(Runnable, long)
postDelayed(Runnable, long)
(6)调用Handler的send方法时,它会调用 MessageQueue 的 enqueueMessage 方法将这个消息放入消息队列中,然后Looper发现有新消息到来时,调用消息中的Runnable或者Handler的 handleMessage方法.
sendEmptyMessage(int)
sendMessage(Message)
sendMessageAtTime(Message, long)
sendMessageDelayed(Message, long)
8. 加入弱引用,防止内存泄漏(另一篇具体讲)
来源:https://blog.youkuaiyun.com/l707941510/article/details/80641444
Handler mHandler = new UpdateUIHandler(new WeakReference<>(this));
public static class UpdateUIHandler extends Handler {
private WeakReference<MainActivity> mainActivityWeakReference;
public UpdateUIHandler(WeakReference<MainActivity> mainActivityWeakReference) {
this.mainActivityWeakReference = mainActivityWeakReference;
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == Parameters.UPDATE_UI_HANDLER_MESSAGE) {
removeMessages(msg.what);
mainActivityWeakReference.get().mFragmentList.clear();
mainActivityWeakReference.get().mApps.clear();
mainActivityWeakReference.get().initData();
}
}
}
9.更新UI的方式
- 使用
Handler的post()方法更新UI - 使用
Handler的sendMessage()方法更新UI - 使用
runOnUiThread()方法更新UI - 使用
View的post()方法更新UI - 子线程中创建
Handler发送消息,在子线程中处理,然后发送给主线程(mHandler) 去更新UI - 在子线程中更新
UI
本文详细解析了Android中Handler的工作原理,包括Handler、Looper、MessageQueue的运作机制,以及如何在不同线程间发送和处理消息,防止内存泄漏,更新UI的方法。
424

被折叠的 条评论
为什么被折叠?



