In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-09 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
本篇内容主要讲解"Handler的原理有哪些",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"Handler的原理有哪些"吧!
总流程
开头需要建立个handler作用的总体印象,下面画了一个总体的流程图
从上面的流程图可以看出,总体上是分几个大块的
Looper.prepare()、Handler()、Looper.loop() 总流程
收发消息
分发消息
相关知识点大概涉及到这些,下面详细讲解下!
需要详细的查看该思维导图,请右键下载后查看
使用
先来看下使用,不然源码,原理图搞了一大堆,一时想不起怎么用的,就尴尬了
使用很简单,此处仅做个展示,大家可以熟悉下
演示代码尽量简单是为了演示,关于静态内部类持有弱引用或者销毁回调中清空消息队列之类,就不在此处展示了
来看下消息处理的分发方法:dispatchMessage(msg)
Handler.java...public void dispatchMessage(@NonNull Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); }}...
从上面源码可知,handler的使用总的来说,分俩大类,细分三小类
收发消息一体
handleCallback(msg)
收发消息分开
mCallback.handleMessage(msg)
handleMessage(msg)
收发一体
handleCallback(msg)
使用post形式,收发都是一体,都在post()方法中完成,此处不需要创建Message实例等,post方法已经完成这些操作
public class MainActivity extends AppCompatActivity { private TextView msgTv; private Handler mHandler = new Handler(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); msgTv = findViewById(R.id.tv_msg); //消息收发一体 new Thread(new Runnable() { @Override public void run() { String info = "第一种方式"; mHandler.post(new Runnable() { @Override public void run() { msgTv.setText(info); } }); } }).start(); }}收发分开mCallback.handleMessage(msg)
实现Callback接口
public class MainActivity extends AppCompatActivity { private TextView msgTv; private Handler mHandler = new Handler(new Handler.Callback() { //接收消息,刷新UI @Override public boolean handleMessage(@NonNull Message msg) { if (msg.what == 1) { msgTv.setText(msg.obj.toString()); } //false 重写Handler类的handleMessage会被调用, true 不会被调用 return false; } }); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); msgTv = findViewById(R.id.tv_msg); //发送消息 new Thread(new Runnable() { @Override public void run() { Message message = Message.obtain(); message.what = 1; message.obj = "第二种方式 --- 1"; mHandler.sendMessage(message); } }).start(); }}handleMessage(msg)
重写Handler类的handlerMessage(msg)方法
public class MainActivity extends AppCompatActivity { private TextView msgTv; private Handler mHandler = new Handler() { //接收消息,刷新UI @Override public void handleMessage(@NonNull Message msg) { super.handleMessage(msg); if (msg.what == 1) { msgTv.setText(msg.obj.toString()); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); msgTv = findViewById(R.id.tv_msg); //发送消息 new Thread(new Runnable() { @Override public void run() { Message message = Message.obtain(); message.what = 1; message.obj = "第二种方式 --- 2"; mHandler.sendMessage(message); } }).start(); }}prepare和loop
大家肯定有印象,在子线程和子线程的通信中,就必须在子线程中初始化Handler,必须这样写
prepare在前,loop在后,固化印象了
new Thread(new Runnable() { @Override public void run() { Looper.prepare(); Handler handler = new Handler(); Looper.loop(); }});
为啥主线程不需要这样写,聪明你肯定想到了,在入口出肯定做了这样的事
ActivityThread.java...public static void main(String[] args) { ... //主线程Looper Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } //主线程的loop开始循环 Looper.loop(); ...}...
为什么要使用prepare和loop?我画了个图,先让大家有个整体印象
上图的流程,鄙人感觉整体画的还是比较清楚的
总结下就是
Looper.prepare():生成Looper对象,set在ThreadLocal里
handler构造函数:通过Looper.myLooper()获取到ThreadLocal的Looper对象
Looper.loop():内部有个死循环,开始事件分发了;这也是最复杂,干活最多的方法
具体看下每个步骤的源码,这里也会标定好链接,方便大家随时过去查看
Looper.prepare()
可以看见,一个线程内,只能使用一次prepare(),不然会报异常的
Looper.java... public static void prepare() { prepare(true);}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));}...
Handler()
这里通过Looper.myLooper() ---> sThreadLocal.get()拿到了Looper实例
Handler.java...@Deprecatedpublic Handler() { this(null, false);}public Handler(@Nullable Callback callback, boolean async) { if (FIND_POTENTIAL_LEAKS) { final Class
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.