Handler的工作原理(一)Handler的使用
16lz
2021-01-23
Handler
的运行机制也是Android
主要的消息机制;
Handler
的主要作用是将一个任务切换到某个指定的线程中去执行;
Q:为什么Android
要提供这种功能呢?
A:Android
规定访问UI
只能在主线程中进行,但Android
又不建议在主线程中进行耗时操作。这时Handler
就排上用场啦,在子线程中进行拉取工作,用Handler
切换一下UI
访问的执行线程来处理UI
操作
好,我们先学会使用,再深入源码理解原理,
常规使用有两种: 一种post()
,一种sendMessage()
post
方法
public class MainActivity extends AppCompatActivity { private static final String TAG = MainActivity.class.getSimpleName(); // post方法 handler的创建 Handler handler = new Handler(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new Thread(new Runnable() { @Override public void run() { /*post方法解决UI更新,直接在runnable里面完成更新操作, 这个任务会被添加到handler所在线程的消息队列中,即主线程的消息队列中*/ handler.post(new Runnable() { @Override public void run() { String result = "更新UI"; Log.d(TAG, "接收到的消息是: " + result); } }); } }).start(); }}
sendMessage
方法
public class MainActivity extends AppCompatActivity { private static final String TAG = MainActivity.class.getSimpleName(); // sendMessage方法 handler的创建 private static Handler sHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); /*sendMessage方法更新UI的操作必须在handler的handleMessage回调中完成*/ switch (msg.what) { case 1: Log.d(TAG, "接收到的消息是: " + msg.obj); break; default: } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new Thread(new Runnable() { @Override public void run() { /*sendMessage方法解决UI更新发送消息给handler(主线程中的handler)*/ Message msg = new Message(); msg.what = 1; msg.obj = "更新UI"; sHandler.sendMessage(msg); } }).start(); }}
两个方法都是在子线中获取到信息后在主线程中访问UI,分析下这两种方法的区别,上源码分析
post方法源码
/** * Causes the Runnable r to be added to the message queue. * 把任务r 添加到消息队列中 */ public final boolean post(Runnable r) { return sendMessageDelayed(getPostMessage(r), 0);//注意这里 } public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); } private static Message getPostMessage(Runnable r) { Message m = Message.obtain(); m.callback = r; return m; }
sendMessage方法源码
public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0);//注意这里 }
可以看出这两个方法最终调用的都是同一个方法sendMessageDelayed()
,所以他们的本质都是一样的,只是用法的区别。post
方法把任务Runable r
包装成了message
。那sendMessageDelayed()
做了什么事,Handler究竟是怎样完成切换线程执行任务的呢,下篇继续深入
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initHandler(); initHandler2(); } /** * 初始化Handler 主线程 */ private void initHandler() { final Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { if(msg.arg1==1) { Toast.makeText(MainActivity.this, "handleMessage", Toast.LENGTH_SHORT).show(); } Log.e("handler",Thread.currentThread().getName()); super.handleMessage(msg); } }; new Thread(new Runnable() { @Override public void run() { Log.e("handler==",Thread.currentThread().getName()); Message message = handler.obtainMessage(); message.arg1 = 1; handler.sendMessage(message); } }).start(); } /** * 初始化Handler 子线程 */ private void initHandler2() { new Thread(new Runnable() { @Override public void run() { Log.e("handler2",Thread.currentThread().getName()); Looper.prepare(); Handler handler = new Handler() {// Handler handler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(Message msg) { if (msg.arg1 == 1) { Toast.makeText(MainActivity.this, "handleMessage", Toast.LENGTH_SHORT).show(); } Log.e("handler2==",Thread.currentThread().getName()); super.handleMessage(msg); } }; Message message = handler.obtainMessage(); message.arg1 = 1; handler.sendMessage(message); Looper.loop(); } }).start(); }}
更多相关文章
- Android退出应用的方法总结
- Android–多线程之Handler下载图片源码
- android基础知识02——线程安全3:Message,MessageQueue,Handler,Loop
- Android内存泄漏的轻松解决方法
- Android中播放声音的两种方法
- Android Activity之间跳转出现短暂黑屏的处理方法和intent.setFl
- 基于xml类型的压缩数据流的android获取天气的方法