Android消息机制详解

Android的消息机制 1.Android消息机制概述 1.1. Android消息机制是什么? Android消息机制主要是指Handler的运行机制以及Handler所附带的MessageQueue和Looper的工作工程,这三者实际上是一个整体,只不过我们在开发过程中比较多的接触到Handler而已。 1.2. Handler的主要作用 Handler的主要作用是将一个任务切换到Handler所在的线程中执行。比如我们经常碰到的一个场景:Android建议不要在主线程中进行耗时操作,否则会导致程序无法响应(A 阅读详情

*本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布

Android消息机制

这一定是一个被写烂了的专题吧。那本媛也来凑一个热闹吧。哈哈
这篇博客将会涉及以下内容:

  • 消息机制概述
  • UML图解消息机制相关类
  • 从在主线程更新UI的方法带你畅游消息机制的源码,更加方便自己理解
  • Handler
  • Looper
  • MessageQueue和Message
  • 消息机制的应用

消息机制概述

Android系统在设计的初期就已经考虑到了UI的更新问题,由于Android中的View是线程不安全的,然而程序中异步处理任务结束后更新UI元素也是必须的。这就造成了一个矛盾,最简单的解决方法肯定是给View加同步锁使其变成线程安全的。这样做不是不可以,只是会有两点坏处:

  1. 加锁会有导致效率底下
  2. 由于可以在多个地方更新UI,开发就必须很小心操作,开发起来就很麻烦,一不小心就出错了。

基于以上两个缺点,这种方式被抛弃。于是机智如我谷歌爸爸。。。设置一个线程专门处理UI控件的更新,如果其他线程也需要对UI进行更新,不好意思,您把您想做的告诉那个专门处理UI线程的家伙,让它帮你做。大家各有各的任务,井水不犯河水,各司其职,效率才会高,不仅仅对于软件如此,人也是如此,我只管写我的代码,有农民伯伯帮我种吃的、有电脑公司卖给我电脑、有建筑公司给我盖房子(当然了,房子我是万万买不起的… 哼!),这些事儿好像自己也能干,但是都自己干好像就回到了远古时代,人类的进步和发展和社会分工的明确也是离不开的,而且关系很大!
好像扯的有点远了。

那么您也看出来了,消息机制其实可以很简单的用一句话概括,就是:其他线程通过给特定线程发送消息,将某项专职的工作,交给这个特定的线程去做。比如说其他线程都把处理UI显示的工作通过发送消息交给UI线程去做。
实现的原理呢,我是这么理解的,现在要做的主要工作就是切换线程去操作,怎么切换呢?把两条线程看作是两条并行的公路,如果要从一条公路转到另一条公路上,要怎么做呢?是不是只要找到两条公路交叉或者共用某个资源的地方,如果说交叉路口,比如说加油站。当然了,线程是不存在交叉的地方的,那么可以考虑他们公用资源的地方,不同的进程享用不同的内存空间,但是同一个进程的不同线程享用的是同一片内存空间,那让其他线程把要处理的消息放到这个特定的内存空间上,处理消息的线程来这个内存空间上来取消息去处理不就可以了吗。事实正是如此,在Android的消息机制中,扮演这个特定内存空间的对象就是MessageQueue对象,发送和处理的消息就是Message对象。其他的Handler和Looper都是为了配合线程切换用的。
其实不仅仅是线程之间,不同进程之间进行消息传递(IPC机制),也是这个思路,找到公用的一个资源点,文件系统啊,共享内存啊等等,这个以后再讲吧。

这样理解起来是不是就是so easy了呢?

UML图解消息机制相关类

不知道上面的说法您是否可以对消息机制有了一个基本的认知呢?我曾经在想,怎么通过很简洁直观的方式去把消息机制讲明白(讲给自己,也讲给你)呢,后来我就在想,当初设计者的思路是什么样的呢?我想到了UML图,用类图来对消息机制中涉及到的几个类有一个概括的认识;通过时序图,可以很清晰的观察到整个消息机制的处理过程。
消息主要设计到下面几个类:

  • Handler:这是消息的发出的地方,也是消息处理的地方。
  • Looper:这是检测消息的地方。
  • MessageQueue:这是存放消息的地方,Handler把消息发到了这里,Looper从这里取出消息交给Handler进行处理
  • Message:呜呜呜…他们发的是我,处理的也是我。
  • Thread:我在这里专门指代的是,处理消息的线程。消息的发送是在别的线程。

话不多说,先来看一张图(UML忘的差不多了,刚补的,如果有错误,麻烦大家指出)

消息机制类图

畅游源码

图在这里了,怎么看呢,整个消息机制相关的类密密麻麻支撑了一张网,咋个看嘛,,,不急不急,咱们先来思考一下咱们常用的更新UI是怎么一个操作步骤。

  1. 在主线程新建一个Handler对象,在构造方法中传入一个实现Handler.Callback接口的匿名类的对象,实现接口中的handleMessage方法
  2. 在非UI线程使用Handler的sendMessage或者post方法发送一个消息
  3. 然后handleMessage方法会在不久的将来马上执行,实现更新UI的操作。

那咱们就跟着这个思路来看一看这张图,先看Handler类,你会发现,Handler真的是个相当关键的核心(当然,其他部分也是不可或缺的),他几乎拥有所有其他相关对象的引用。

  • Handler拥有Looper的引用,通过得到Looper对象获得Looper中保存的MessageQueue对象
  • Handler拥有MessageQueue的引用,使Handler得以拥有发送消息(将Message放入MessageQueue)的能力
  • Handler拥有Handler.Callback的引用,使得Handler可以方便的进行消息的处理。
来思考一个问题:为什么Handler在其他线程发送消息之后,就跑到了主线程的handleMessage方法中去更新UI?

这个问题暂时先放着,等下回过头再来看。
我们现在先跟着第1,2,3步看看系统都帮我们做了什么操作呢?这就是在看源码,不要觉得很高深
下面是鲜活的代码,为了方便您查看,我帮您摘出来了。如果有兴趣,您也可以在AS里点开看看


    //这是在主线程中
    Handler handler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {

            switch (msg.what) {
                case 1:
                    Toast.makeText(mContext, "你真漂亮", Toast.LENGTH_SHORT).show();
                    break;
                case 2:
                    Toast.makeText(mContext, "你也很帅呢", Toast.LENGTH_SHORT).show();
                    break;
                default:
                    break;
            }
            return false;
        }
    });

    //这是我们在主线程中创建Handler时会使用的构造方法
    public Handler(Callback callback) {
        this(callback, false);//调用了下面的这个构造方法↓
    }

    //先不要管第二个参数。跟紧主线,别跟丢了
    public Handler(Callback callback, boolean async) {
        if (FIND_POTENTIAL_LEAKS) {
            final Class<? extends Handler> klass = getClass();
            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                    (klass.getModifiers() & Modifier.STATIC) == 0) {
                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                    klass.getCanonicalName());
            }
        }

          //在这里获取到Looper对象,怎么获取的,稍后再看
        mLooper = Looper.myLooper();
        //如果获取的mLooper为空,直接抛出异常,说你不能在一个没有调用Looper.prepare()方法
        //的线程里创建Handler
        //如此看来,Looper.prepare()方法重要的嘞
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
        //通过mLooper对象获取MessageQueue这个消息队列(单链表)
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

到此为止,一个Handler就创建好了,(还有一个问题是Looper.prepare方法很重要,但是我们还没有去考虑他是干嘛的,不急不急,先顺着一条线看,不然看源代码的过程会把你搞死翘翘的)先面就该进行第二步,看看Handler.sendMessage干了啥.代码段又来喽

    //在一个新建的线程里使用创建好的Handler发送一个消息
    new Thread(new Runnable() {
        @Override
        public void run() {
            //在这儿干点你想干的吧,一些耗时的计算或者网络操作啥的
            Message message = new Message();
            message.what = 1;
            handler.sendMessage(message);
        }
    }).start();

    //直接调用的是这个函数
    public final boolean sendMessage(Message msg){
        return sendMessageDelayed(msg, 0);
    }

    //转而调用了这个函数
    public final boolean sendMessageDelayed(Message msg, long delayMillis)
    {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }

    //转而又来到了这里
    public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;
        if (queue == null) {
            RuntimeException e = new RuntimeException(
                    this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
            return false;
        }
        return enqueueMessage(queue, msg, uptimeMillis);
    }

    //最后的最后来到了这里
    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        //target就是Message绑定的Handler,看看类图,上面有这个细节
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        //最后的最后,调用了MessageQueue的enqueueMessage方法
        return queue.enqueueMessage(msg, uptimeMillis);
    }

    //再看一下MessageQueue的enqueueMessage方法,
    //我把其他一些无关的细节给删掉了,只为了更加容易阅读
    boolean enqueueMessage(Message msg, long when) {
        synchronized (this) {
            Message p = mMessages;
            if (p == null) {
                // New head, wake up the event queue if blocked.
                msg.next = p;
                mMessages = msg;
            } else {
                //下面的错误就是遍历单链表,找到链表的尾部,这个没有难度的吧?
                Message prev;
                for (;;) {
                    prev = p;
                    p = p.next;
                    if (p == null || when < p.when) {
                        //找到了尾部,现在的结构是这样的。
                        //A->B->C...->pre(p)->null
                        break;
                    }
                }
                msg.next = p; // invariant: p == prev.next
                prev.next = msg;//把next插入链表的尾部
            }
        }
        return true;
    } 

到此为止,第二步就结束了,成功把一个消息插入到了MessageQueue的尾部。可是你很快就会发现,第三步好像从这条路探寻不下去了。接下来就等着别人来调用Handler中的方法了,可是是谁调用的,在哪儿调用的?我们现在好像毫无头绪了?怎么办?怎么办?我们刚才不是看到一个Looper.myLooper(),和Looper.prepare()方法,说是很重要但是一直没看吗,既然现在搜寻不下去了,是不是可以回头看看了?还有一点,Looper,看起来是在循环,循环什么玩意儿呢?我们去好好看看Looper类吧。
一共就三百来行代码,仔细看看,你会发现有一个核心方法:Looper.loop();
同样的,我把影响阅读的非主线代码剔除了,发现Looper.loop方法就长这样:

    /**
     * Run the message queue in this thread. Be sure to call
     * {@link #quit()} to end the 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;
        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
            try {
                msg.target.dispatchMessage(msg);
            } finally {

            }
        }
    }

清晰可见的是,Looper.loop()方法一直遍历MessqgeQueue,阻塞线程,直到获取到一个Message,然后调用了Message的一个成员变量target(其实就是Handler)的dispatchMessage(msg)方法,嗨,还真的又跟Handler扯上关系了,既然这里扯上关系了,而且还是一个分发消息的方法,可以大胆猜测就是让Handler去处理这个消息的。
那么我们来看看这个方法:

    /**
     * Handle system messages here.
     * 如果Message中callback对象不为空(这是调用handler.post(Runnable)方法发送的消息),
     * 就调用callback的run方法
     * 否则如果创建Handler的时候如果设置了Callback就调用创建时候的传入的
     * 实现Handler.Callback接口的类的对象的handleMessage方法,看这就是回调方法被调用的地方。
     * 再如果没有mCallback对象,就调用自身的handleMessage方法,为了Handler的子类复写了该方法的时候,方便调用,如,IntentService里的ServiceHandler就是继承自Handler的,并且重写了handleMessage方法。
     */
    public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

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

    //ServiceHandler继承自Service并且重写了handleMessage方法
    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            onHandleIntent((Intent)msg.obj);
            stopSelf(msg.arg1);
        }
    }

到了这里,三步走已经看完了,我想消息机制在我们心里已经又清晰了一层,但是不用急,咱们前边提的一个问题不是还没有解决吗,先把他解决掉吧,一起继续来看源码。
咱们现在已知的是这样的,在主线程创建的Handler发送了一个消息,发送消息的代码运行在其他线程,将代码加入消息队列也是在其他线程(加了线程同步锁)。然后handleMessage发生在主线程,那么调用该方法的dispatchMessage方法也是运行在主线程的,dispatchMessage是在Looper.loop方法中调用的,也就是说loop方法也运行在主线程,那么问题就明朗了,可是loop方法是谁调用的,在哪里调用的呢?当然是系统启动的时候创建主线程之后再主线程的run方法中调用了Looper.prepare和Looper.loop方法,但是这点我还没看,留着以后再看吧。
然后通过上面的分析,我们是不是可以自己来试着建立这样一个模型:

  1. 创建一个线程A
  2. 在这个线程的run方法中调用Looper.prepare和Looper.loop方法使该线程阻塞,等待消息发过来,然后处理
  3. 在该线程中创建一个Hanlder,用来处理looper发送来的待处理的消息
  4. 创建一些其他的线程a、b、c,做一点操作之后,通过Handler把消息传递出去,让线程A去处理。
public class MyThread extends Thread {
    private static final String TAG = "MyThread";

    Handler handler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            switch (msg.what) {
                case 1:
                    Log.i(TAG,"你真漂亮");
                    break;
                case 2:
                    Log.i(TAG,"你也很帅呢");
                    break;
                default:
                    break;
            }
            return false;
        }
    });


    public Handler getHandler() {
        return handler;
    }

    @Override
    public void run() {
        super.run();
        Looper.prepare();
        Looper.loop();
    }

    @Override
    public void destroy() {
        super.destroy();
        Looper.myLooper().quit();
    }
}

//
    private void testMyThread() {
        MyThread thread = new MyThread();
        thread.start();
        final Handler handler = thread.getHandler();

        Message message = new Message();
        message.what = 1;
        handler.sendMessage(message);

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    sleep(400);
                    Message message = new Message();
                    message.what = 2;
                    handler.sendMessage(message);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

试着想一想,如果把线程A看成主线程,在回调方法更新UI,那这不就是Android系统中更新UI使用的套路吗?不错,事实本就如此,工具是工具,用它来更新UI是可以的,那你当然也可以用来做一些其他的工作啊。

在这里,通过以上的分析,不难得到下面的这个整个消息机制运行过程的时序图:

时序图

ok啦,源码阅读到此为止。其他的细节,有兴趣的可以再细细研究一下。
下面我们来对涉及到的类进行一下总结。
先来说一下我的个人理解,

Handler

handler在消息机制中,扮演的是消息的发送方和处理方(通过回调函数)。消息在一个线程通过Handler发送到MessageQueue中。Looper获取到Message之后,根据Message中保存的handler对象调用handler对象的dispatch方法,进行消息的处理。

Looper

Looper在这里扮演的是一个轮询消息队列的角色,以为不停地去问MessageQueue要消息,得到消息之后,根据Message中保存的handler对象调用handler对象的dispatch方法,进行消息的处理。

MessageQueue和Message

MessageQueue实质上是一个单链表的结构,里面以链表的形式保存着Handler发送过来的消息,当有新消息发来时放在链表的尾部,Looper要取消息的时候从链表的头部取出消息返回给Looper处理。Message对象中保存在要处理的信息,同时也持有消息发送方(Handler)的引用,Looper在得到该Message的时候,可以从Message中拿到消息的发送方,调用发送方的回调方法将消息传递过去交给Handler进行处理。

消息机制的应用

在Android中有很多消息机制的应用,如:

  • UI的更新
  • HandlerThread
  • IntentService

UI的更新

UI线程持有一个Looper对象,Looper对象的loop方法在UI线程中一直不停的进行死循环,直到有新的消息发来的时候,交给特定的组件进行处理,当然了这个处理也是在主线程运行的(如我们设置的点击事件也是等着被UI线程调用的),正是由于这个原因,我们不能在主线程处理耗时操作。如果我们一个View的点击事件里做了大量耗时的操作,由于这个操作也在主线程中运行,主线程必须等着这个操作操作结束才能去处理其他的消息,这个时候表现的就是系统卡顿甚至报ANR的错误。

HandlerThread

HandlerThread继承自Thread,内部保存一个Looper对象。
这是一个系统帮我们包装好的Thread,这个线程的run方法已经调用了Looper.prepare和Looper.loop(即已经绑定了一个Looper对象,并且可以开始轮询消息),创建该对象之后可以通过获得对象获取到一个Looper对象,将Looper对象传递给Handler,完成Handler和Looper以及MessageQueue的绑定。最后再其他的线程中调用Handler的sendMessage或者post(Runable)方法发送消息,handler中的callback.handleMessage方法会在HandlerThread中运行。即,将消息发送到了特定的线程(此处是HandlerThread)处理。

IntentService

IntentService继承自Service,运行时优先级更高,内部使用了HandlerThread作为处理消息的线程。内部有一个私有内部类ServiceHandler继承自Handler,并且会创建一个ServiceHandler对象。
使用startService()方法启动IntentService时,不会重新创建一个服务,会调用ServiceHandler对象发送包含该Intent的Message对象,该对象通过HandlerThread处理后交给ServiceHandler重写的handleMessage方法进行处理,处理的方式是调用IntentService的onHandleIntent(Intent)方法,所以使用的方式就是创建一个继承自IntentService类的子类,并重写onHandleIntent方法,在该方法中处理startService时传递的Intent。Intent中包含有要交给Service处理的信息。

android的消息机制——Handler机制 能简单说得我们尽量不复杂:为了避免ANR,我们会通常把 耗时操作放在子线程里面去执行,因为子线程不能更新UI,所需当子线程需要更新的UI的时候就需要借助到安卓的消息机制,也就是Handler机制了。 注意:在安卓的世界里面,当 子线程 在执行耗时操作的时候,不是说你的主线程就阻塞在那里等待子线程的完成——也不是调用 Thread.wait()或是Thread.sleep()。安卓采取的方法是, 阅读详情

相关推荐

详解Android的消息机制

Android的消息机制 本人初学Android,可能会因为文章中的一些错误而对您造成了困扰,万分抱歉,如有错误欢迎您在评论区指正。 文章目录Android的消息机制概述一、pandas是什么?二、使用步骤1.引入库2.读入数据总结 概述 Handler是Android消息机制的上层接口,所以Android的消息机制主要指的就是Handler的运行机制,其主要应用于UI线程(主线程)和子线程之间的交互。众所周知,一般情况下,出于安全的考虑,所有与UI控件的操作都要放在主线程,而一些耗时的I/O操作应

AthonyDavis的博客 1322

Android 消息机制

Android 消息机制

EnHengNa的博客 1004

安卓中的消息循环机制Handler及Looper详解

我们知道安卓中的UI线程不是线程安全的,我们不能在UI线程中进行耗时操作,通常我们的做法是开启一个子线程在子线程中处理耗时操作,但是安卓规定不允许在子线程中进行UI的更新操作,通常我们会通过Handler机制来完成该功能,即当子线程中耗时操作完成后,在子线程中通过Handler向主线程发送消息,在主线程中的Handler的handleMessage方法中处理接受到的消息。这就是安卓中的消息机制,安

(* ̄︶ ̄) 7960

Android 知识总结:消息机制

Android 的消息机制主要是指 Handler 的运行机制以及 Handler 所附带的 MessageQueue 和 Looper 的工作过程,这三者实际上是一个整体,只不过我们在开发过程中比较多地接触到 Handler 而已。

耐心的L的博客 1116

告别密码烦恼:用Windows Server NPS给公司Wi-Fi和有线网加一道MAC地址白名单(附H3C交换机配置)

本文详细介绍了如何利用Windows Server NPS(网络策略服务器)与H3C交换机实现MAC地址白名单认证,为企业Wi-Fi和有线网络提供零密码安全方案。通过配置NPS服务器、网络策略及H3C交换机联调,实现无感知认证体验,降低运维负担,同时满足审计追溯需求。适用于中小企业网络管理,提升安全性与便捷性。

weixin_42535703的博客 367

MATLAB/simulink电力系统之变压器仿真+变压器饱和仿真+空载变压器电流畸变原因及仿真+空载合闸励磁涌流仿真+simulink免费仿真资源

单相变压器空载运行时,原边电流主要用来产生主磁场,而电路损耗和铁芯损耗很小,因此即使外加电压很大,空载电流仍然很小。如果想观察某个相对磁导率下电感系数的数值,可以在程序中增加这样的语句,比如,在程序中end语句之后,加上L(100),运行程序后就可以得到相对磁导率为 100时的电感系数值。在交流铁芯线圈中,当交变磁通按照正弦规律变化时,受到磁路饱和的影响,线圈中的电流会发生畸变,并成为尖顶波,这就是所谓的交流磁路电流畸变。需要指出,铁芯内的主磁通Ф可以通过空载时的副边电压从来测量,两者之间的数学关系,即。

m0_37724753的博客 4230

Android的消息机制结合代码示例详解

Android消息机制主要是指Handler的运行机制以及Handler所附带的MessageQueue和Looper的工作工程,这三者实际上是一个整体,只不过我们在开发过程中比较多的接触到Handler而已。

大模型训练 440

IVP 2021 UNETR: Transformers for 3D Medical Image Segmentation

动机 具有跟踪和扩展路径的全卷积神经网络(FCNNs)(如编码器和解码器),近年来在各种医学图像分割应用中显示出了突出的地位。在这些体系结构中,编码器通过学习全局上下文表示来扮演一个不可或缺的角色,该全局上下文表示将进一步用于解码器的语义输出预测。 卷积层作为FCNN的主要构造块,其局部性限制了此类网络学习长时空间依赖的能力。 在NLP领域,基于transformer的模型已经在各种任务中实现了最先进的基准。transformer中的自我注意机制使他们能够动态地突出词序列的重要特征并学习其长时依赖关系。这

smile909的博客 1979

安卓开发中Android消息机制详解

在Android程序运行中,线程之间或者线程内部进行信息交互时经常会使用到消息,如果我们熟悉这些基础的东西及其内部的原理,将会使我们的Android开发变的容易、可以更好地架构系统。在学习Android消息机制之前,我们先了解与消息有关的几个类:   1.Message   消息对象,顾名思义就是记录消息信息的类。这个类有几个比较重要的字段:   a.arg1和arg2:我们可以

zhangkongzhongyun的专栏 621

5分钟搞定Unity+Visual Studio开发环境配置(含C#游戏开发工作负载)

本文提供了一份详细的Unity与Visual Studio开发环境配置指南,帮助开发者在5分钟内完成C#游戏开发工作负载的设置。从Unity Hub安装到Visual Studio关键组件选择,再到常见问题排查,全面覆盖环境搭建的各个环节,显著提升游戏开发效率。

weixin_29014237的博客 248

芒果YOLO11改进81:主干Backbone篇之DCNv3结构:即插即用|使用pytorch代码实现,并针对YOLO11专门优化模块

芒果YOLO11改进81:主干Backbone篇之DCNv3结构:即插即用|使用pytorch代码实现,并针对YOLO11专门优化模块

包括YOLOv5、YOLOv7、YOLOv8等模型改进 737

Android Handler消息机制详解

在Android中,只有主线程才能更新UI,但是主线程不能进行耗时操作,否则会产生ANR异常,所以常常把耗时操作放到其他子线程进行。如果在子线程中需要更新UI,一般都是通过Handler发送消息,主线接收消息后进行相应的UI逻辑处理。 一.什么是Handler Handler是一个消息分发对象。 Handler是Android系统提供的一套用来更新UI的机制,也是一套消息处理机制,可以通过Handler发消息,也可以通过Handler处理消息。 二.为什么使用Handler 为了解决多

Android23333的博客 1851

UG\NX二次开发 判断对象是虚线还是实线

网友提问“怎么区分虚线实线”,这个可以通过函数判断。

王牌飞行员_里海的博客 357

Android开发——Android的消息机制详解

1. 为什么需要Android的消息机制 Android规定访问UI只能在主线程中进行。若在子线程中访问UI就会抛出异常。这个验证由ViewRootImpl的checkThread()来完成。 为什么不允许在非主线程访问UI呢?这是因为Android的UI控件不是线程安全的。并且UI访问没有锁机制,并发访问会导致控件处于不可预期的状态。 那为什么不对UI访问加上锁机制呢? (1)这显然会......

关于Android开发的一些技术点总结 ╮( ̄▽ ̄”)╭ 1万+

基于Simulink的鲸鱼优化算法(WOA)MPPT仿真

摘要:本文介绍了基于Simulink的鲸鱼优化算法(WOA)在光伏MPPT控制中的应用。WOA模拟座头鲸的"气泡网捕食策略",通过包围猎物、螺旋收缩和随机搜索三阶段动态平衡全局探索与局部开发能力,有效解决局部阴影导致的多峰P-V曲线问题。文章详细讲解了WOA-MPPT的Simulink建模过程,包括多峰光伏阵列建模、WOA控制器实现和Boost变换器控制。仿真结果显示,在三种典型工况下,WOA-MPPT的追踪效率>99.3%,动态响应时间<0.15s,性能优于传统算法。最后提出了混合WO

amy_mhd的博客 72

用 AI 设计力打造专业 UI_UX:在 Trea、Qoder 等 AI IDE 中集成 ui-ux-pro-max-skill

的核心是知识库Trea 和 Qoder 虽未被--ai all原生支持,但完全可通过@folder手动集成使用后,你的 AI 生成代码将从“功能可用”跃升至“设计专业”这是零成本提升产品质感的最佳实践之一🎨好的 UI 不应是设计师的专利,而是每个开发者的默认能力。然后在 Trea 或 Qoder 中输入—— 让 AI 成为你最懂设计的结对编程伙伴。

lpfasd123的博客 7101

android消息机制原理详解

android消息机制原理详解Android消息机制概述说到Android的消息机制,Android初级工程师(不包括那些初学者)肯定会想到Handler。是的,Android的消息机制主要是指Handler的运行机制以及Handler所附带的MessageQueue和Looper的工作过程。当我们工作的时候我们只要接触到Handler就可以了。为什么要有Android消息机制?我们知道Handle

欧阳帆的专栏 9046

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Android的消息机制Handler详解

Android的消息机制详解 Android的消息机制主要指 Handler 的运行机制

YoungTr的专栏 3558

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

安卓php推送消息机制,Android_Android消息处理机制Looper和Handler详解,Message:消息,其中包含了消息 - phpStudy...

Android消息处理机制Looper和Handler详解Message:消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理。Handler:处理者,负责Message的发送及处理。使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等。MessageQu...

weixin_35101659的博客 218

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

安卓Handler消息处理机制详解

消息处理机制可以算得上是每个安卓开发入行最先接触的机制之一。它为我们提供了一种线程间通信方式。本文就讲解Handler提供的各种用法以及其运行机理。

lingchen881218的博客 2315

Android 消息机制详解

Android 消息机制详解 消息机制简介 Handler、Message、MessageQueue、Looper一起实现了android的消息机制。那,什么是消息机制,上述四个类是干什么?又是怎么实现了线程间的消息传递的?我们先来概括一下。 消息机制主要解决线程间的数据传递问题。 Handler负责发送和处理消息。Message封装了线程间传递的数据,Message内部有一个Message next的对象,指向下一个消息,这样可以通过第一个Message来遍历所有的消息了。Mess.

qq_30329621的博客 1052

Android中消息机制详解

Android 线程问题主要概念1、MessageQueue:是一种数据结构,见名知义,就是一个消息队列,存放消息的地方。每一个线程最多只可以拥有一个MessageQueue数据结构。创建一个线程的时候,并不会自动创建其MessageQueue。通常使用一个Looper对象对该线程的MessageQueue进行管理。主线程创建时,会创建一个默认的Looper对象,而Looper对象的创建,将自动创建

Fast_Soo_So的博客 361

Android 读写队列,详解Android 消息处理机制

摘要Android应用程序是通过消息来驱动的,当Android主线程启动时就会在内部创建一个消息队列。然后进入一个无限循环中,轮询是否有新的消息需要处理。如果有新消息就处理新消息。如果没有消息,就进入阻塞状态,直到消息循环被唤醒。那么在Android系统中,消息处理机制是怎么实现的呢?在程序开发时,我们经常会使用Handler处理Message(消息)。所以可以知道Handler是个消息处理者,M...

weixin_42370434的博客 2949
上一篇: Android Intent 基础
下一篇: 项目中一些bug的修复
ApiPlayer
博客等级 码龄12年 34粉丝 17原创
评论 15
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值