我们之前都是使用sendMessage()方法来发送消息,使用handleMessage来处理消息的,今天我们来看另外一种方法,先看代码:

package cn.lixyz.handlertest;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView; public class MainActivity extends Activity { private Button button;
private Handler handler = new Handler();
private TextView textView; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); textView = (TextView) findViewById(R.id.textView);
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
TestThread t = new TestThread();
t.start();
}
}); } class TestThread extends Thread {
@Override
public void run() {
super.run();
Runnable r = new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
Log.d("TTTT", (i + 1) + " 秒");
try {
Thread.sleep(1000 * 1);
textView.setText("5秒后修改的内容");
} catch (InterruptedException e) {
e.printStackTrace();
} }
}
}; handler.post(r);
}
} }

MainActivity.java

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity"> <TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:gravity="center"
android:text="更改前"
android:textSize="30sp" /> <Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="30dp"
android:text="Send Message" /> </LinearLayout>

acitivit_main.xml

点击按钮,运行结果:

从代码中我们可以看到,我新建了一个线程,线程中创建了一个Runnable对象,这个Runnable对象中有修改UI的操作,然后使用调用了Handler的 post() 方法,那么我们就来看一下这个 post() 究竟是如何实现的。

查看Handler的源代码,找到post()方法

    public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}

我们发现,其实post方法直接调用了一个延时发送消息的方法 sendMessageDelayed() ,只不过延时为0,继续找到 getPostMessage() 方法

    private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}

在上面的代码中,我们发现,getPostMessage方法内新获取了一个Message对象,并且将我们传入的Runnage对象赋值给了这个Message对对象的 callback 属性,然后将之返回

所以说, post() 方法的本质就是将一个Runnable对象赋值给一个Message属性的 callback 属性,然后将这个Message对象放入到消息队列当中去

而之前我们说过,Looper的 loop() 方法会循环的从消息队列中取出消息,那么这时候Looper是怎么工作的呢,找到Looper的 loop() 方法

    public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue; // Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity(); for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
} // This must be in a local variable, in case a UI event sets the logger
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
} msg.target.dispatchMessage(msg); if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
} // Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
} msg.recycle();
}
}

和之前说的一样,loop()方法执行之后,同样的先拿到Looper对象,之后开始循环从消息队列中取出消息,执行到 msg.target.dispatchMessage(msg); 因为Message的 target 属性是 Handler 类型的,我们去看Handler的 despatchMessage 方法

    public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}

可见,先进对收取到的Message对象的 callback 属性进行判断,如果不为空,为调用 handleCallback 方法,查看 handleCallback 方法

    private static void handleCallback(Message message) {
message.callback.run();
}

message.callback.run(); 直接调用了Runnable对象的 run() 方法,而不是创建一个新线程,然后再调用这个线程的start方法。

最新文章

  1. 多线程之异步编程: 经典和最新的异步编程模型,async与await
  2. Async and Await 异步和等待
  3. Java学习一
  4. jsp分页代码之pageUtil类
  5. JQuery replace 替换全部
  6. mybatis 主键UUID生成策略
  7. Echarts环形进度使用 【1 简单的使用示例】
  8. Apache Spark 2.2.0 中文文档 - Submitting Applications | ApacheCN
  9. python中的slice用法
  10. CSS3之border-radius圆角
  11. Python-Jupyter Notebook使用技巧
  12. 关于AMD 、CMD、 commonjs的认识
  13. &lt;笔记&gt;原生PHP访问TP模板变量
  14. Spring Boot 构建电商基础秒杀项目 (三) 通用的返回对象 &amp; 异常处理
  15. 微信小程序地图报错——ret is not defined
  16. stm32启动文件ld md hd cl vl xl分析及选择
  17. shell编程:基本语法
  18. C++中的npos,size_t,size_type
  19. codeforces水题100道 第六题 Yandex.Algorithm 2011 Qualification 2 A. Double Cola (math)
  20. sencha touch 在线实战培训 第一期 第六节

热门文章

  1. 123457123456#1#----com.MC.EnglishGame98--前拼后广--jp英语-mc
  2. 【docker 镜像源】解决quay.io和gcr.io国内无法访问的问题
  3. DB2中ALTER TABLE的使用
  4. 【Leetcode_easy】944. Delete Columns to Make Sorted
  5. nnexus3 破解密码
  6. Office 2010 经验总结
  7. 如何提高程序员的键盘使用效率(搬砖工人的自我修养(tucao))
  8. php类的继承(基本概念,访问权限修饰符,重写override)
  9. 在ensp上简单的配置交换机
  10. Mysql 排序优化