• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Android > 深入了解android中的消息机制Handler

深入了解android中的消息机制Handler

作者:网友 字体:[增加 减小] 来源:互联网 时间:2017-05-26

网友通过本文主要向大家介绍了深入了解android,深入了解,深入了解 英文,深入了解的近义词,深入了解 英语等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

深入了解android中的消息机制Handler


什么是Handler?
handler是Android给我们提供用来更新UI的一套机制,也是一套消息处理机制.
我们可以使用它发送消息,也可以通过它处理消息.

我们为什么要使用Handler?
Android在设计的时候,就封装了一套消息创建,传递,处理机制,如果不遵循这样的机制,就没有办法更新UI,而且还会抛出异常信息.

例如:大家都知道,更新UI的操作一般都是放在main线程中,当我们需要在子线程中更新UI时,就需要使用到了Handler,虽然在子线程更新Ui的方法有好几种,但内部实现原理基本都是通过Handler发送消息处理的,不要着急,下面会提到.

Handler的使用:

sendMessage()方法的使用:
package com.hnthgys.mytext;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    private TextView tv;
    //创建main线程的Handler
    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            tv.setText("我是通过handler发送消息更新的");
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tv = (TextView) findViewById(R.id.textview);
        //开启子线程
        new Thread(){
            @Override
            public void run() {
                super.run();
                //例如此处我们正在执行一个耗时操作,执行完毕后发送消息更新ui

                //发送一个空消息
                handler.sendEmptyMessage(0);

                //如果此处我们需要使用执行完耗时操作的数据,可以这样写
                //Message msg = handler.obtainMessage();
                //msg.obj = "数据";
                //handler.sendMessage(msg);

            }
        }.start();


    }
}

sendEmptyMessage(); 此方法和sendMessage使用一致,区别就是发送一个空消息.

sendMessageDelayed(); 发送一个延时执行的消息

post(Runnable);该方法可以在子线程中更新UI,该方法运行在main线程中

removeCallbacksAndMessages();移除回调和消息;例如:我们在使Handler轮播一些图片时,想让它停止轮播,就可以使用这个方法.

android为什么要设计只能通过handler来更新UI呢?

最根本的的目的就是解决多线程并发问题.假设如果在一个activity当中,有多个线程去更新UI,并且都没有加锁机制,那么会产生什么样子的问题呢? 更新界面错误.

你可能会说,我可以使用加锁的多线程啊,如果对更新UI的操作都进行加锁处理的话,应用程序的性能会大大下降.
处于对以上问题的考虑,Android给我们提供了一套更新UI的机制,我们只需要遵循这样的机制就可以了.
根本不用关心多线程的问题,所以更新UI的操作,都是在主线程的消息队列当中去轮询处理的.

Handler的原理是什么呢?
一,Handler封装了消息的发送,(主要包括消息发送给谁)
Looper(Handler内部自己的Looper)
1,内部包含一个消息队列,也就是MessageQueue,所有的Handler发送消息
都走向这个消息队列.
2,Looper.loop()方法,就是一个死循环,不断的从MessageQueue中取消息,
如果有消息就处理消息,没有消息就阻塞.

二,MessageQueue,就是一个消息队列,可以添加消息,并处理消息.

三,Handler,内部会跟Lopper进行关联,也就是说在Handler的
内部可以找到Looper,找到了Lopper也就找到 了MessageQueue,
在Handler中发送消息,其实就是向MessageQueue队列中发送消息.

Handler原理总结:
Handler负责发送消息,Loooper负责接收Handler发送的消息,
并直接把消息回传给Handler自己.
MessageQueue就是一个存储消息的容器.

Handler使用中遇到的问题:
在非UI线程中更新UI,抛出的异常:
这里写图片描述
在子线程创建Handler,抛出的异常:
这里写图片描述
注意:当需要在子线程中创建Handler时,需要先创建一个Looper,因为子线程中没有Looper对象

HandlerThread又是什么?

当我们向创建一个与线程相关的Handler时,我们可以使用HandlerThread,来解决多线程的并发问题.
这里写图片描述

子线程与主线程如何互发消息:

主线程Handler向子线程发送消息(伪代码)
这里写图片描述 子线程Handler向主线程发送消息(伪代码)
这里写图片描述

Android在子线程中更新UI的几种方式:
使用图片吧,以前做的笔记,看着感觉更加清晰..
这里写图片描述

非UI线程真的不能更新UI吗?
答案是能,对.你没有看错,非UI线程也能更新UI.可能你会觉得我在扯淡,下面看一段代码:

package com.hnthgys.mytext;

import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    private TextView tv;
    //创建main线程的Handler
    private Handler handler = new Handler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tv = (TextView) findViewById(R.id.textview);
        //开启子线程
        new Thread(){
            @Override
            public void run() {
                super.run();
                //SystemClock.sleep(100);
                tv.setText("我是在子线程中更新的UI");
            }
        }.start();


    }
}

我把布局代码也贴出来,





    


执行效果图:
这里写图片描述

可能看到这,你已经目瞪口呆了,这怎么可能,fuck,这完全颠覆了啊…..

主要原因:
当我们在更新UI时,Android中的ViewRootImpl类中的checkThread()方法会检查当前更新UI所在的线程,如图

3937    void More ...checkThread() {
            //检查执行更新UI所在的线程
3938        if (mThread != Thread.currentThread()) {
                //如果不在UI线程,就会抛出下面的异常,大家应该很眼熟吧
3939            throw new CalledFromWrongThreadException(
3940                    "Only the original thread that                 created a view hierarchy can touch its views.");
3941        }
3942    }

查看系统源码后,你会发现,ViewRootImpl类会在 Activity的onResume()方法执行完成后才初始化,这也就解释了上面代码能运行的原因了,但是,你发现没有,我们在子线程中没有做任何的耗时操作,如果我在子线程中添加这句代码:

SystemClock.sleep(100);

那么系统将会抛出异常:”Only the original thread that created a view hierarchy can touch its views.”
不能在非UI线程中更新UI.
那么问题来了,如果ViewRootImpl类没有初始化完成,那么view视图是如何显示出来的呢???我也正在解决中…….

另外,当我们在子线程中获取到ViewRoot,我们可以调用addView()方法在子线程中更新UI,这其中的详情就靠大家去探索了…..

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 深入了解android中的消息机制Handler

相关文章

  • 2017-05-26Play 2D games on Pixel running Android Nougat (N7.1.2) with Daydream View VR headset,nougatn7.1.2
  • 2017-05-26Android中View的事件分发机制——Android开发艺术探索笔记
  • 2017-05-26JSON解析和XML解析对比,JSON解析XML解析
  • 2017-05-26在不同Activity之间传递数据的四种常用方法,activity四种
  • 2017-05-26Couldn't load libPassword from loader:NDK开发中C文件编译成cpu的so类库时,找不到类库报错的原因之一,libpasswordndk
  • 2017-05-26粗暴的解释Android与蓝牙Ble之间的通信,android蓝牙ble
  • 2017-05-26android开发中遇到的问题汇总【九】
  • 2017-05-26Android网络编程的Socket通信总结
  • 2017-05-26Activity猫的一生-故事讲解Activity生命周期,activity生命周期
  • 2017-05-26解析Service之你需要了解的一些东东,解析Service之东东

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • android 和Ubuntu 同步使用Xmind
    • Linux内核系列—5.操作系统开发之特权级及特权级的转移,linux特权
    • Android 手机卫士--参照文档编写选择器,android选择器
    • 2.4.3 Date & Time组件(下)
    • Android开发笔记(9)——初步设置Menu,androidmenu
    • Unity实现滑页嵌套(解决ScrollRect嵌套冲突问题)
    • App更新之dialog数字进度条,appdialog进度条
    • Android 5.0(包含5.0以下版本) 获取栈顶应用程序包名,android包名
    • 浅谈Kotlin(一):简介及Android Studio中配置,kotlinandroid
    • 【Android开发】完美解决Android完全退出程序,开发android

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有