1.Message:

Message 是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间进行数据交换。除了 what 字段,还可以使用 arg1 和 arg2 来携带整型数据,使用 obj 来携带 Object 数据。

2、Handler:

Handler主要用于发送和处理消息的。发送消息一般是使用Handler的sendMessage()方法,而发出的消息经过一系列的处理后,最终会传递到Handler的handleMessage()方法中。

3、MessageQueue:

MessageQueue是消息队列,主要用于存放所有通过Handler发送的消息。这部分消息会一直存放在于消息队列中,等待被处理。每个线程中只会有一个MessageQueue。

4、Looper:

用于管理 MessageQueue 队列,调用 Looper.loop() 方法之后,就会进入无限循环中,每当发现 MessageQueue 存在一条消息,就会将它取出,并传递到 Handler 的 handleMessage() 方法中。每个线程中只会有一个 Looper 对象。

了解了Message、Handler、MessageQueue和Looper的基本概念后,我们再通过图例来更清晰地理解异步消息处理,如下图所示:

可以清晰地看到整个异步消息的处理过程。首先需要在UI县城中创建一个Handler对象,然后在子线程中调用Handle的sendMessage()方法,接着这个消息会存放在UI线程的MessageQueue中,通过Looper对象取出MessageQueue中的消息,最后分发会Handler的handleMessage()方法中。

二、异步消息处理机制实现


Handler机制

  • Handler 的使用

Handler 有两种使用方法,一种是 sendMessage(Message) ,另一种是 post(Runnable)。通过修改上述例子来进行展示。

修改main_activity布局,在原基础上添加一了一个按钮:

<?xml version="1.0" encoding="utf-8"?>

<android.support.constraint.ConstraintLayout xmlns:android=“http://schemas.android.com/apk/res/android”

xmlns:app=“http://schemas.android.com/apk/res-auto”

xmlns:tools=“http://schemas.android.com/tools”

android:layout_width=“match_parent”

android:layout_height=“match_parent”

tools:context=".MainActivity">

<Button

android:id="@+id/sendMessage"

android:layout_width=“match_parent”

android:layout_height=“wrap_content”

android:text=“sendMessage()”

app:layout_constraintTop_toTopOf=“parent”

app:layout_constraintRight_toRightOf=“parent”

app:layout_constraintLeft_toLeftOf=“parent” />

<Button

android:id="@+id/post"

android:layout_width=“match_parent”

android:layout_height=“wrap_content”

android:text=“post()”

app:layout_constraintHorizontal_bias=“0.0”

app:layout_constraintLeft_toLeftOf=“parent”

app:layout_constraintRight_toRightOf=“parent”

app:layout_constraintTop_toBottomOf="@id/sendMessage" />

<TextView

android:id="@+id/text"

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:text=“Hello World!”

app:layout_constraintBottom_toBottomOf=“parent”

app:layout_constraintLeft_toLeftOf=“parent”

app:layout_constraintRight_toRightOf=“parent”

app:layout_constraintTop_toTopOf=“parent” />

</android.support.constraint.ConstraintLayout>

修改MainActivity:

package com.example.threaddemo;

import android.os.Handler;

import android.os.Message;

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.view.View;

import android.widget.Button;

import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

private TextView text;

private Button but_send;

private Button but_post;

private static final int SENDMESSAGE=1;

//创建handler

private Handler handler1=new Handler(){

public void handleMessage(Message msg){

switch(msg.what){//将接收到的消息与SENDMESSAGE进行匹配

case SENDMESSAGE:

text.setText(“sendMessage()”);

break;

default:

break;

}

}

};

private Handler handler2=new Handler();

private final Runnable runnable = new Runnable() {

@Override

public void run() {

//更新UI显示

MainActivity.this.text.setText(“post()”);

}

};

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

text=(TextView)findViewById(R.id.text);

but_send=(Button)findViewById(R.id.sendMessage);

but_post=(Button)findViewById(R.id.post);

but_post.setOnClickListener(this);

but_send.setOnClickListener(this);

}

@Override

public void onClick(View v){

switch(v.getId()){

//Handler的sendMessage()方法

case R.id.sendMessage:

new Thread(new Runnable() {

@Override

public void run() {

Message msg = new Message();

msg.what = SENDMESSAGE;

handler1.sendMessage(msg);

}

}).start();

break;

//Handler的post方法

case R.id.post:

new Thread(new Runnable() {

@Override

public void run() {

handler2.post(runnable);

}

}).start();

break;

default:

break;

}

}

}

实现效果展示:

观察sendMessage()的源码和post()的源码:

/**

*Pushes a message onto the end of the message queue after all pending messages

  • before the current time.

  • 将消息添加到消息队列。

*/

public final boolean sendMessage(Message msg)

{

return sendMessageDelayed(msg, 0);

}

/**

  • Causes the Runnable r to be added to the message queue.

  • 把任务对象r添加到消息队列中。

*/

public final boolean post(Runnable r)

{

return sendMessageDelayed(getPostMessage®, 0);

}

/**

*Enqueue a message into the message queue after all pending messages

*post方法中调用发送延时消息的方法,把这个消息放入消息队列。

*/

public final boolean sendMessageDelayed(Message msg, long delayMillis)

{

if (delayMillis < 0) {

delayMillis = 0;

}

return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);

}

/post中调用的另外一个方法,我们很容易看出来,这个方法就是把任务r包装成了一个空的消息并且返回/

private static Message getPostMessage(Runnable r) {

Message m = Message.obtain();

m.callback = r;

return m;

}

可以看出handler.post和handler.sendMessage本质上是没有区别的,都是发送一个消息到消息队列中,而且消息队列和handler都是依赖于同一个线程的。

  • Handler内存泄漏问题及其解决办法

Android用java语言编写的,其中java提供了自动的GC机制(Garbage Collection)即垃圾回收机制,采用对象引用计数的方式。在分析Handler导致的内存泄漏问题前我们自然先要了解GC是怎么回收内存的。

首先,Java的垃圾回收机制使用有向图机制,通过GC自动检查内存中的对象,如果GC发现一个或一组对象为不可到达状态,则将该对象从内存中回收。也就是说,一个对象不被任何引用所指向,则该对象会在被GC发现的时候被回收;另外,如果一组对象中只包含互相的引用,而没有来自它们外部的引用(例如有两个对象A和B互相持有引用,但没有任何外部对象持有指向A或B的引用),这仍然属于不可到达,同样会被GC回收。

private Handler handler=new Handler(){

public void handleMessage(Message msg){

switch(msg.what){//将接收到的消息与SENDMESSAGE进行匹配

case SENDMESSAGE:

text.setText(“sendMessage()”);

break;

default:

break;

}

}

};

上段是关于上文例子中的Handler的使用(即使用内部类的方式来创建Handler)。当使用内部类(包括匿名类)来创建Handler的时候,Handler对象会隐式地持有一个外部类对象(通常是一个Activity)的引用。而Handler通常会伴随着一个耗时的后台线程(例如从网络拉取图片)一起出现,这个后台线程在任务执行完毕(例如图片下载完毕)之后,通过消息机制通知Handler,然后Handler把图片更新到界面。然而,如果用户在网络请求过程中关闭了Activity,正常情况下,Activity不再被使用,它就有可能在GC检查时被回收掉,但由于这时线程尚未执行完,而该线程持有Handler的引用(即当完成图片下载时会加消息传给Handler),这个Handler又持有Activity的引用,就导致该Activity无法被回收(即内存泄露),直到网络请求结束(例如图片下载完毕)。另外,如果你执行了Handler的postDelayed()方法,该方法会将你的Handler装入一个Message,并把这条Message推到MessageQueue中,那么在你设定的delay到达之前,会有一条MessageQueue -> Message -> Handler -> Activity的链,导致你的Activity被持有引用而无法被回收。这样会导致程序内存溢出,程序崩溃。

对于这个问题,有两种解决方法:

1、一种是将 Handler 设置成静态内部类,由于Handler不再持有外部类对象的引用,导致程序不允许你在Handler中操作Activity中的对象了。所以你需要在Handler中增加一个对Activity的弱引用(即添加WeakReference对Activity的弱引用);

static class MyHandler extends Handler{

WeakReference mWeakReference;

public MyHandler(Activity activity)

{

mWeakReference=new WeakReference(activity);

}

@Override

public void handleMessage(Message msg)

{

final Activity activity=mWeakReference.get();

if(activity!=null)

{

if (msg.what == SENDMESSAGE)

{

//更新UI信息

TextView text=(TextView)activity.findViewById(R.id.text);

text.setText(“sendMessage”);

}

}

}

}

2、第二种是在 Activity 的生命周期 onDestroy() 中调用Handler的removeCallback()方法,撤销 Handler 在 Activity 上的回调,让Activity 能成功被释放,避免内存泄漏。

@Override

学习分享

在当下这个信息共享的时代,很多资源都可以在网络上找到,只取决于你愿不愿意找或是找的方法对不对了

很多朋友不是没有资料,大多都是有几十上百个G,但是杂乱无章,不知道怎么看从哪看起,甚至是看后就忘

如果大家觉得自己在网上找的资料非常杂乱、不成体系的话,我也分享一套给大家,比较系统,我平常自己也会经常研读。

2020最新上万页的大厂面试真题

七大模块学习资料:如NDK模块开发、Android框架体系架构…

只有系统,有方向的学习,才能在段时间内迅速提高自己的技术。

这份体系学习笔记,适应人群:
第一,学习知识比较碎片化,没有合理的学习路线与进阶方向。
第二,开发几年,不知道如何进阶更进一步,比较迷茫。
第三,到了合适的年纪,后续不知道该如何发展,转型管理,还是加强技术研究。如果你有需要,我这里恰好有为什么,不来领取!说不定能改变你现在的状态呢!
464/Android-P7/blob/master/Android%E5%BC%80%E5%8F%91%E4%B8%8D%E4%BC%9A%E8%BF%99%E4%BA%9B%EF%BC%9F%E5%A6%82%E4%BD%95%E9%9D%A2%E8%AF%95%E6%8B%BF%E9%AB%98%E8%96%AA%EF%BC%81.md)

[外链图片转存中…(img-kVCA5A1p-1646147536232)]

七大模块学习资料:如NDK模块开发、Android框架体系架构…

[外链图片转存中…(img-rZ4BTi3L-1646147536233)]

只有系统,有方向的学习,才能在段时间内迅速提高自己的技术。

这份体系学习笔记,适应人群:
第一,学习知识比较碎片化,没有合理的学习路线与进阶方向。
第二,开发几年,不知道如何进阶更进一步,比较迷茫。
第三,到了合适的年纪,后续不知道该如何发展,转型管理,还是加强技术研究。如果你有需要,我这里恰好有为什么,不来领取!说不定能改变你现在的状态呢!
由于文章内容比较多,篇幅不允许,部分未展示内容以截图方式展示 。如有需要获取完整的资料文档的朋友点击我的GitHub免费获取。

以下未发布-Android的多线程以及异步消息处理机制,android移动开发基础案例教程源码相关推荐

  1. Android异步消息处理机制完全解析,带你从源码的角度彻底理解

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/9991569 之前也是由于周末通宵看TI3比赛,一直没找到时间写博客,导致已经有好久 ...

  2. [学习总结]6、Android异步消息处理机制完全解析,带你从源码的角度彻底理解

    开始进入正题,我们都知道,Android UI是线程不安全的,如果在子线程中尝试进行UI操作,程序就有可能会崩溃.相信大家在日常的工作当中都会经常遇到这个问题,解决的方案应该也是早已烂熟于心,即创建一 ...

  3. Android多线程----异步消息处理机制之Handler

    虽然是国庆佳节,但也不能停止学习的脚步,我选择在教研室为祖国母亲默默地庆生. 关于Android的多线程知识,请参考本人之前的一篇博客:Android 多线程----AsyncTask异步任务详解 在 ...

  4. Android之多线程----异步消息处理机制之Handler详解

    一.handler的引入: 我们都知道,Android UI是线程不安全的,如果在子线程中尝试进行UI操作,程序就有可能会崩溃.相信大家在日常的工作当中都会经常遇到这个问题,解决的方案应该也是早已烂熟 ...

  5. Android Handler 异步消息处理机制的妙用 创建强大的图片载入类

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38476887 ,本文出自[张鸿洋的博客] 近期创建了一个群.方便大家交流,群号: ...

  6. Android异步消息处理机制 全解析

    Android异步消息处理机制主要是指Handler的运行机制以及Hanlder所附带的MessageQueue和Looper的工作过程. 本文将通过分析源码(api-28)的形式,全面解析Handl ...

  7. Android线程之异步消息处理机制(二)——Message、Handler、MessageQueue和Looper

    异步消息处理机制解析 Android中的异步消息处理主要有四个部分组成,Message.Handler.MessageQueue和Looper. 1.Message Message是在线程之间传递的消 ...

  8. Android开发之异步消息处理机制AsyncTask

    转自:Android AsyncTask完全解析,带你从源码的角度彻底理解 另外一篇比较详细的博文:http://blog.csdn.net/liuhe688/article/details/6532 ...

  9. Android异步消息处理机制 深入理解Looper、Handler、Message三者关系

    转载子:http://blog.csdn.net/lmj623565791/article/details/38377229 ,本文出自[张鸿洋的博客] 很多人面试肯定都被问到过,请问Android中 ...

最新文章

  1. 小型网站到大型网站-Mysql优化
  2. 能上qq打不开网页,金山毒霸帮你解决
  3. 泛型擦除机制、自定义注解、代理、反射
  4. HDU1010 Tempter of the Bone dfs(奇偶减枝)
  5. SAP Spartacus Popover Component 显示与否的逻辑判定
  6. php 新浪url,PHP URL函数详解
  7. Python 测试驱动开发(四)测试及重构的目的(上)
  8. 手把手带你一起写迅雷官网
  9. python摄像头识别快递单号查询_免费对接快递鸟api单号识别查询接口(python)
  10. 8位可控加减法电路设计_C++手撕底层:位、字节、原码、反码、补码的深入理解...
  11. 理解linux下的load
  12. mix2线刷开发板救砖_小米MIX2线刷刷机教程_小米MIX2第三方rom包_线刷救砖教程
  13. appium安装教程
  14. 使用gitLab clone代码报错:error: RPC failed; curl 56 OpenSSL SSL_read: Connection was reset
  15. 彻底关闭Windows10自动更新的详细解决方案
  16. 计算机科学是期刊核心2类,属于计算机技术类的北大核心期刊有哪些
  17. 第三周项目 侦察队委派任务
  18. 嵌入式Linux小项目之图片编解码播放器(5)
  19. Python 给视频添加水印
  20. 1-8 (4). RabbitMQ高级特性-消费端ACK

热门文章

  1. 【2019年秋PAT乙级考试】回顾 +题解+思路2019-9-8
  2. android+仿ios画廊,安卓仿ios14主题app
  3. jack server无法启动
  4. 内存申请 GFP_KERNEL GFP_ATOMIC
  5. 【学术相关】国家自然科学基金申请——函评等级与上会
  6. python invoking c++
  7. TCP 三次握手原理,你真的理解吗?
  8. 数据库(单表查询与多表联查)
  9. halcon变量,图像与C++的一些转换(未完待续)
  10. 机器学习中训练的模型,通俗理解