Android 中 Handler的使用和源码详细分析

Android——Handler详解 1. 简介 Handler是一套 Android 消息传递机制 可以说只要有异步线程与主线程通信的地方就一定会有 Handler。 在多线程的应用场景中,将工作线程中需更新UI的操作信息 传递到 UI主线程,从而实现 工作线程对UI的更新处理,最终实现异步消息的处理 使用Handler消息传递机制主要是为了多个线程并发更新UI的同时,保证线程安全 2. 相关概念解释 Handler、Message、Message Queue、Looper Android消息机制: 以Handler的sendMes 阅读详情
1、Handler在Android中的作用

在Android中Android系统为我们封装了一套多线程间消息通信的机制—handle机制,主要用来多线程间的消息传递、用来更新UI操作。

2、 Handler的实现机制

在说handle的实现机制之前,首先先了解几个基本概念:

  • Handler 消息的发送者和处理者
  • Message 消息传递的载体
  • Loop 轮询器 负责从消息队列中取出消息,分发给handle
  • MessageQueue 维护存储handle发送过来的消息队列

在这里插入图片描述

3、Handle的具体使用
3.1 子线程发消息给UI线程

(1) 创建Handler 发送消息和重写handleMessage处理消息,采用内部静态类的方式去定义Handle 是因为非静态内部类默认持有外部类的引用,Activity销毁的时候容易引起内存泄漏,但是使用静态类的,handle中需要一个activity的引用,所有采用弱引用的方式去持有外部Activity的引用,当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。

 static class MyHandle extends Handler{
  
        WeakReference<Activity > mActivityReference;

        MyHandle(Activity activity) {
            mActivityReference= new WeakReference<>(activity);
        }
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            MyTheadActivity activity = (MyTheadActivity) mActivityReference.get();
            activity.textView.setText("接收到数据:"+msg.arg1);
        }
    }
    MyHandle myHandle=new MyHandle(this); 

创建子线程发送数据

 new Thread(){
            @Override
            public void run() {
                super.run();
                while (num>0){
                    try {
                        num--;
                        Thread.sleep(100);
                        Message message = Message.obtain();
                        message.arg1=num;
                        myHandle.sendMessage(message);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start(); 
3.2 UI线程发消息给子线程

在子线程中创建Handle对象;

private void initSubThread() {
        new Thread(){
            @Override
            public void run() {
                super.run();
                Looper.prepare();
                myHandle1 =new MyHandle(MyTheadActivity.this);
                Looper.loop();

            }
        }.start();
    } 

主线程中发送消息到子线程

 textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Message msg = Message.obtain();
                msg.arg1=100;
                myHandle1.sendMessage(msg);
            }
        }); 

整个流程在子线程中创建handle 对象,在主线程发送消息。

08-05 21:53:34.963 1782-1795/camera.test.com.networkdata E/TAG: 线程名称:Thread-77接收到消息:100 

这个时候在创建Handle 的时候调用了2个方法 Looper.prepare(); Looper.loop(); 这两个方法是弄啥类,

之前说过 handle 发送消息是发送到一个Message Queue中,然后Looper轮询从MessaeQueue队列中取出消息,然后通过dispatchMessage 方法分发消息,最终handle中handleMessage处理消息。 那么肯定需要一个Looper对象和MessageQueue消息队列 来配合Handle多线程中消息传递。 接下来通过主线程发送消息到子线程的例子来看下源码都具体干了啥。

4、handle 源码看看

从上边的主线程发消息到子线程开始,加入不调用Looper.prepare(); Looper.loop(); 方法会怎么样。

08-05 22:08:12.423 1897-1916/camera.test.com.networkdata E/AndroidRuntime: FATAL EXCEPTION: Thread-80
    Process: camera.test.com.networkdata, PID: 1897
    java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
        at android.os.Handler.<init>(Handler.java:200)
        at android.os.Handler.<init>(Handler.java:114)
        at camera.test.com.networkdata.MyTheadActivity$MyHandle.<init>(MyTheadActivity.java:29)
        at camera.test.com.networkdata.MyTheadActivity$2.run(MyTheadActivity.java:68) 

发现 程序直接崩溃了,意思就是mLooper不能为空。需要个Looper,这个错误我们也可以通过查看Handle的源码看到

源码分析一:
 public Handler(Callback callback, boolean async) {
          ....
          省略一些代码
        mLooper = Looper.myLooper();   //源码分析二
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread " + Thread.currentThread()
                        + " that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    } 

可以看到 Looper.myLooper(); 获取的Looper对象为null的时候就抛出RuntimeException异常。

源码分析二: Looper.myLooper();

从ThreadLocal 中获取Looper对象

 static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
   
 /**
     * Return the Looper object associated with the current thread.  Returns
     * null if the calling thread is not associated with a Looper.
     */
    public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    } 
源码分析三: Looper.prepare();

通过以上分析一和分析二知道,子线程中使用handle必须需要一个Looper否则就会报错,那接下在看下Looper.prepare(); 都做了些什么

 public static void prepare() {
        prepare(true);
    }
	
    private static void prepare(boolean quitAllowed) {
     //解释一: 一个线程中只能有一个Looper对象
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread"); 
        }
        解释二: 通过ThreadLocal 存储Looper对象
        
        sThreadLocal.set(new Looper(quitAllowed)); // 源码分析四
    } 

总结:一个线程中只能有一个Looper对象,创建的Looper对象通过ThreadLocal进行存储,和创建Handle时候的sThreadLocal.get(); 相对应。

源码分析四: new Looper(quitAllowed)
 private Looper(boolean quitAllowed) {
 		解释一 :创建消息队列
        mQueue = new MessageQueue(quitAllowed);
        解释二 : 绑定到当前线程
        mThread = Thread.currentThread();
    } 

总结:终于看到MessageQueue 了,再不见还以为他是个摆设呢,创建Looper对象的时候,自动创建MessageQueue 消息队列。

通过以上分析:知道Looper.prepare(); 创建了 Looper对象和MessageQueue消息队列对象,并绑定到当前线程。以上只是创建了Looper和MessageQueue,并没有见如何 轮询从MessageQueue中取出数据,接下来就看下Looper.loop();

源码分析五: Looper.loop();
 public static void loop() {
 //  解释一 :获取Looper对象
        final Looper me = myLooper();
  //解释二 :如果looper是null抛出异常
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
    //解释三 :获取MessageQueue  消息队列
        final MessageQueue queue = me.mQueue;
        
          省略一些代码
     
     // 解释四 : 开启一个无限循环从MessaQueue中取出消息
     
        for (;;) {
        消息队列中取出消息,消息为空return
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }

          省略了一些代码
          
            try {
           // 解释五: 	取出的消息进行消息分发,msg.target 是啥呀?就是发送消息的Handle 对象,
           最终调用的是handle中 dispatchMessage方法/
                msg.target.dispatchMessage(msg);    源码分析 六
                dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
            } finally {
                if (traceTag != 0) {
                    Trace.traceEnd(traceTag);
                }
            }
        
            msg.recycleUnchecked();
        }
    } 

总结: 通过以上代码知道,Looper.loop(); 就是looper 轮询器开始循环的从消息队列中取出数据,然后交给Handle去处理。

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

总结:通过看handle中的dispatchMessage方法,发现如果mCallback 不为null的时候,最终调用handleMessage()方法,也就是我们经常重写处理消息的方法。

总结:通过以上分析,可以得出handle同过sendMessage方法发送消息,到消息队列然后looper从消息队列中取出消息然后最终还是交给handle去处理,那么handle是怎么和Looper、MessaheQueue进行关联的的嘞?接下来看下 创建Hanlde过程中都做了那些操作。

源码分析 七 创建Handle过程

Handle创建有几种方式

第一类:不需要指定Looper对象,

 public Handler() {}
 
 public Handler(boolean async){}
 
 public  Handler(Callback callback) {}
  
 public Handler(Callback callback, boolean async) {}
 
 
第二类:自己传一个Looper 对象

 public Handler(Looper looper){}

 public Handler(Looper looper, Callback callback){}
 
 public Handler(Looper looper, Callback callback, boolean async) {} 

先看下第一种创建方式,第一种最终都会调用 public Handler(Callback callback, boolean async) {} 方法

public Handler(Callback callback, boolean async) {
      
       省略一些代码
      //获取Looper对象,之前源码分析二中分析过了
        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread " + Thread.currentThread()
                        + " that has not called Looper.prepare()");
        }
        // 初始化消息队列
        mQueue = mLooper.mQueue;
        // 初始化回调 ,这个回调是干什么的?之后再说
        mCallback = callback;
        // 是否异步
        mAsynchronous = async;
    } 

总结 :通过以上创建Handle的源码,发现初始化了Looper对象和mQueue 消息队列,callback回调,

然后再看下第二种创建方式,最后调用的是 public Handler(Looper looper, Callback callback, boolean async) {}

public Handler(Looper looper, Callback callback, boolean async) {
        mLooper = looper;
        mQueue = looper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    } 

和第一种方式区别不是很大,只是Looper是自己创建的,传进来的,注意Lopoer在那个线程创建,这个线程就属于一个Looper线程。

总结:通过以上源码可以知道,在创建Handle的时候,handle和当前的线程的Looer、messageQueue进行关联的。然后handle发送消息到MessageQueue中,looper从MessageQueue取出消息,交给handle处理,整个流程就已经清晰可见。但是handle是怎么发送消息到消息队列的呢。

源码分析 八 消息发送
第一种 sendXXX 系列 最终都调用的是 sendMessageAtTime

public final boolean sendMessage(Message msg)

public final boolean sendEmptyMessage(int what){}

public final boolean sendEmptyMessageDelayed(int what, long delayMillis) 

public final boolean sendMessageDelayed(Message msg, long delayMillis)

public boolean sendMessageAtTime(Message msg, long uptimeMillis) 

第二种  postXX系列  其实最红调用的也是 sendMessageAtTime方法

 public final boolean post(Runnable r)

 public final boolean postAtTime(Runnable r, long uptimeMillis)

 public final boolean postAtTime(Runnable r, Object token, long uptimeMillis)

 public final boolean postDelayed(Runnable r, long delayMillis) 

第一种和第二种方法不一样的地方就是,第二种方法需要一个Runnable 接口。很熟悉者不是创建线程的时候的Runnable 的么怎么这里也用到看下 public final boolean post(Runnable r)

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

getPostMessage( r ) 获取一个Message对象

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

Runnable 直接赋值给Messge的callback了。那么有什么用呢,这个看下面的handle的dispatchMessage方法。

接下来看下sendMessageAtTime

public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
		获取到MessageQueue
        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);
    } 

enqueueMessage方法

 private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
  // 当前handle对象赋值给 message的target 指定处理message对象
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        
        return queue.enqueueMessage(msg, uptimeMillis);
    } 

queue.enqueueMessage 存放消息到消息队列 (大概知道就行)

 boolean enqueueMessage(Message msg, long when) {
        if (msg.target == null) {
            throw new IllegalArgumentException("Message must have a target.");
        }
        if (msg.isInUse()) {
            throw new IllegalStateException(msg + " This message is already in use.");
        }

        synchronized (this) {
         省略一些代码
         // 整体意思就是 ,按照消息发送时间存放到对列当中 ,存放成功返回True 
            msg.when = when;
            Message p = mMessages;
            boolean needWake;
            if (p == null || when == 0 || when < p.when) {
                // New head, wake up the event queue if blocked.
                msg.next = p;
                mMessages = msg;
                needWake = mBlocked;
            } else {
                // Inserted within the middle of the queue.  Usually we don't have to wake
                // up the event queue unless there is a barrier at the head of the queue
                // and the message is the earliest asynchronous message in the queue.
                needWake = mBlocked && p.target == null && msg.isAsynchronous();
                Message prev;
                for (;;) {
                    prev = p;
                    p = p.next;
                    if (p == null || when < p.when) {
                        break;
                    }
                    if (needWake && p.isAsynchronous()) {
                        needWake = false;
                    }
                }
                msg.next = p; // invariant: p == prev.next
                prev.next = msg;
            }

            // We can assume mPtr != 0 because mQuitting is false.
            if (needWake) {
                nativeWake(mPtr);
            }
        }
        return true;
    } 

总结:以上就是发送消息的整个过程。通过sendXXX或者postXXX方法最终都调用的是sendMessageAtTime()方法将消息发送到Message Queue消息队列中,并指定消息处理对象。

上边说到postXX的方式,传入一个Runnable接口,最终赋值给Message的callBack,那么到底有什么用呢再次看下dispatchMessage

 public void dispatchMessage(Message msg) {
 // 看到了把 如果msg.callback != null 调用  handleCallback(msg);
        if (msg.callback != null) {
            handleCallback(msg);
        } else {  
         //mCallback 又是什么 ,通过第一种创建 Handle方式,
            有一个参数为Callback ,这也是一个接口,如果不为空的话,就直接调用 他的 handleMessage 
            进行消息处理,   否则再交给 handle自己的handleMessage 处理
            if (mCallback != null) { 
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    } 

看下 handleCallback 都做了什么

 private static void handleCallback(Message message) {
    //  最终调用的是 接口run方法。 而且不会再走    handleMessage(msg); 方法了
        message.callback.run();
    } 

通过dispatchMessage 方法得知 Handle 的handleMessage 处理消息优先级最低,只要我们的 msg.callback 和mCallback 不为空,都可以拦截 handle的消息处理。

总结 : 以上是handle在多线程中通信的整个分析流程,在当前线程创建Looper和MessageQueue对象,并将Handle与之绑定,将当前线程变成Looper线程,并开启对消息队列的监听,handle通过发送消息到MessageQueue,然后通过Looper取出消息,并交给handle处理,还可以通过handle发送消息的方式,进行对handle的handleMessage 进行拦截处理。

5 、那为什么没见UI线程创建Looper和MessageQueue呢?

那是因为在程序启动的时候,系统已经帮我们创建好了具体代码看ActivityThread的main方法

 public static void main(String[] args) {
  
      //  省略一些代码

        Looper.prepareMainLooper();

        ActivityThread thread = new ActivityThread();
        thread.attach(false);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }

     //   省略一些代码
      
        Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    } 

以上代码就是系统启动的时候帮我们创建的,具体创建和上边分析的差不多,就不多说了

文末

要想成为架构师,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
在这里插入图片描述
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

一、架构师筑基必备技能

1、深入理解Java泛型
2、注解深入浅出
3、并发编程
4、数据传输与序列化
5、Java虚拟机原理
6、高效IO
……

在这里插入图片描述

二、Android百大框架源码解析

1.Retrofit 2.0源码解析
2.Okhttp3源码解析
3.ButterKnife源码解析
4.MPAndroidChart 源码解析
5.Glide源码解析
6.Leakcanary 源码解析
7.Universal-lmage-Loader源码解析
8.EventBus 3.0源码解析
9.zxing源码分析
10.Picasso源码解析
11.LottieAndroid使用详解及源码解析
12.Fresco 源码分析——图片加载流程

在这里插入图片描述

三、Android性能优化实战解析

  • 腾讯Bugly:对字符串匹配算法的一点理解
  • 爱奇艺:安卓APP崩溃捕获方案——xCrash
  • 字节跳动:深入理解Gradle框架之一:Plugin, Extension, buildSrc
  • 百度APP技术:Android H5首屏优化实践
  • 支付宝客户端架构解析:Android 客户端启动速度优化之「垃圾回收」
  • 携程:从智行 Android 项目看组件化架构实践
  • 网易新闻构建优化:如何让你的构建速度“势如闪电”?
  • …

在这里插入图片描述

四、高级kotlin强化实战

1、Kotlin入门教程
2、Kotlin 实战避坑指南
3、项目实战《Kotlin Jetpack 实战》

  • 从一个膜拜大神的 Demo 开始

  • Kotlin 写 Gradle 脚本是一种什么体验?

  • Kotlin 编程的三重境界

  • Kotlin 高阶函数

  • Kotlin 泛型

  • Kotlin 扩展

  • Kotlin 委托

  • 协程“不为人知”的调试技巧

  • 图解协程:suspend

在这里插入图片描述

五、Android高级UI开源框架进阶解密

1.SmartRefreshLayout的使用
2.Android之PullToRefresh控件源码解析
3.Android-PullToRefresh下拉刷新库基本用法
4.LoadSir-高效易用的加载反馈页管理框架
5.Android通用LoadingView加载框架详解
6.MPAndroidChart实现LineChart(折线图)
7.hellocharts-android使用指南
8.SmartTable使用指南
9.开源项目android-uitableview介绍
10.ExcelPanel 使用指南
11.Android开源项目SlidingMenu深切解析
12.MaterialDrawer使用指南
在这里插入图片描述

六、NDK模块开发

1、NDK 模块开发
2、JNI 模块
3、Native 开发工具
4、Linux 编程
5、底层图片处理
6、音视频开发
7、机器学习

在这里插入图片描述

七、Flutter技术进阶

1、Flutter跨平台开发概述
2、Windows中Flutter开发环境搭建
3、编写你的第一个Flutter APP
4、Flutter开发环境搭建和调试
5、Dart语法篇之基础语法(一)
6、Dart语法篇之集合的使用与源码解析(二)
7、Dart语法篇之集合操作符函数与源码分析(三)
…
在这里插入图片描述

八、微信小程序开发

1、小程序概述及入门
2、小程序UI开发
3、API操作
4、购物商场项目实战……

在这里插入图片描述

全套视频资料:

一、面试合集
在这里插入图片描述
二、源码解析合集

在这里插入图片描述
三、开源框架合集

在这里插入图片描述
欢迎大家一键三连支持,若需要文中资料,直接点击文末优快云官方认证微信卡片免费领取【保证100%免费】↓↓↓
在这里插入图片描述

Android Handler机制(线程间通信)↑ 在Android中,提供了异步消息处理机制的两种方式来解决线程之间的通信问题,一种是Handler机制,还有一种是AsyncTask机制。 1.handler 我们都知道,Android UI是线程不安全的,如果在子线程中尝试进行UI操作,程序就会崩溃。相信大家在日常的工作当中都会经常遇到这个问题,解决的方案应该也是早已烂熟于心,即创建一个Message对象,然后借助Handler发送出去,之后在Handler的handleMessage()方法中获得刚才发送的Message对象,然后在这里进行UI操作就不 阅读详情

相关推荐

嵌入式设备电量显示实战:MCP3421 ADC采集从原理到代码全解析(附避坑指南)

本文详细解析了嵌入式设备中MCP3421 ADC芯片在电量显示应用中的硬件设计、寄存器配置、I2C通信调试及低功耗优化策略。通过实战代码和避坑指南,帮助开发者实现高精度电量监测,特别针对I2C时序和分压电路设计等常见问题提供解决方案,适用于物联网终端和移动设备开发。

weixin_42525632的博客 386

Android 中 Handle的使用和源码详细分析

文章目录1、Handle在Android中的作用2、 Handle的实现机制3、Handle的具体使用3.1 子线程发消息给UI线程3.2 UI线程发消息给子线程4、handle 源码看看`源码分析一:``源码分析二:` Looper.myLooper();`源码分析三:` Looper.prepare();`源码分析四:` new Looper(quitAllowed)`源码分析五:` ...

苏打水解渴的博客 1137

华为海思2026届数字IC秋招笔试高频考点解析与实战技巧(2025最新版)

本文深入解析华为海思2026届数字IC秋招笔试的高频考点与实战技巧,涵盖时序优化、低功耗设计、DFT规则等核心模块。针对2025年最新真题,提供详细的解题思路和工程经验,帮助考生高效备考。特别关注SystemVerilog约束随机测试等新增考点,助力考生在秋招笔试中脱颖而出。

m2n3o4p5的博客 415

android 线程保存图片,Android使用线程获取网络图片

感谢老罗视频教程,感谢各位的代码分享捕获.PNGAndroidManifest.xmlpackage="com.zdcrobot.handlermessage">android:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:supportsRtl="tru...

weixin_42599908的博客 280

贝塞尔曲线基础

贝塞尔曲线于1962年由法国工程师皮埃尔·贝塞尔(Pierre Bézier)所广泛发表,他运用贝塞尔曲线来为汽车的主体进行设计。贝塞尔曲线最初由Paul de Casteljau于1959年运用de Casteljau演算法开发,以稳定数值的方法求出贝兹曲线。

YiYeZhiNian的博客 2045

emqx Java 订阅以及发送 结合若依框架

emqx Java 订阅以及发送 结合若依框架

Spo的博客 1613

Handle介绍

转载:https://blog.youkuaiyun.com/summer_ck/article/details/53201009 一:接下来我来说明一下Handle的用途 Handle到底是什么,我们为什么要来使用Handle,Handle 其实跟Intent有点类似,这里我直说类似,没有说什么是一样的啊,这种话,不是我说的,intent是用来实现四大组件之间的通信用的,而Handle呢?这个它的用途就...

liudongdong_jlu 3545

融合Retinex理论与Transformer的YOLOv8低光照目标检测增强方法【YOLOv8】

图像分解:将输入图像分解为光照成分和反射成分。光照估计:估计光照图以消除暗光区域。图像重建:将光照增强后的反射图像重建成最终图像。Retinexformer通过在Transformer中引入Retinex的图像增强思路,使得低光照图像的细节能够得到充分保留。本文提出了一种基于Retinexformer的低光照增强方法,用于改进YOLOv8模型在夜间和低光照环境下的目标检测性能。

博客 1929

Android异步相关源码详细分析(Handler、Message、Looper、MessageQueue)

详细介绍Android异步处理以及相关的Handler、Message、MessageQueue、Looper等源码分析

RobotHost的博客 848

YOLO26改进策略【YOLO和Mamba】| MLLA:Mamba-Like Linear Attention,融合Mamba设计优势的注意力机制

本文记录的是利用模块优化的目标检测网络模型。模块具有独特优势。它不同于传统模块,能同时兼顾局部特征高效建模与长距离交互学习。常见模块要么在局部特征处理上有优势但长距离交互能力弱,要么反之,而模块克服了此问题。它融合了Mamba模型和线性注意力机制的优势,通过独特的结构设计,能够在保持计算效率的同时,精准地建模局部特征并学习长距离交互信息。本文将其用于的模型改进和二次创新,能够更加关注图像中的重要特征区域,抑制背景等无关信息的干扰,从而突出目标物体的关键特征。Demystify Mamba in Vision

Limiiiing的博客 213

使用 ABAP Development Tool 登录 SAP BTP ABAP 环境时,遇到弹出框应该怎么办?

但在实际环境里,隐私模式、第三方 Cookie 禁止、跨站追踪限制、缓存代理误命中、混合内容拦截等因素,都可能让这条跳转链路被打断。等),浏览器会弹出系统原生登录框,请求用户输入账号和口令或做集成认证。只要它们在响应头里出现,浏览器就会理直气壮地弹框,这是协议层的强约定。,最终弹出原生登录框。前端与网关领域有个通用的经验规则:如果你看到了原生登录框,而期望的是带样式的。环境里的登录方式表述为基于浏览器的前端认证,也就是这类重定向式的交互。环境的具体落地,拆出几类常见诱因与排障路径,并穿插真实世界的案例。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 369

Android Handler源码分析

做了一年的Android业务,感觉自己的Android能力并没有得到多大提升,下定决心开始阅读Android源码,就从使用最频繁的Handler开始吧。 Handler定义 言归正传,首先Handler是什么,可能大部分人都不太清楚。但大家一定知道,UI线程不能做耗时操作,所有的耗时操作都要扔到子线程中去执行,那问题来了,子线程又不能更新UI,那这时候在耗时操作中要更新UI怎么实现呢? 这时候Android就给我们提供了Handler,通过Handler可以将子线程中的消息抛到主线程中去执行,或者说可以将任

m0_37673128的博客 172

路径跟踪 | 图解路径跟踪PID算法(附ROS C++/Python/Matlab仿真)

PID控制是一种经典的控制算法,广泛应用于各种工业场景。在基于PID的局部路径规划中,希望机器人能快速跟踪上预设的轨迹。本文介绍PID控制的基本原理,并基于PID控制律设计路径跟踪算法,最后通过ROS C++/Python/Matlab进行仿真实现,加深理解

FRIGIDWINTER的博客 1万+

android handler的机制和原理_Android消息机制的原理及源码解析

提起Android消息机制,想必都不陌生。其中包含三个部分:Handler,MessageQueue以及Looper,三者共同协作,完成消息机制的运行。本篇文章将由浅入深解析Android消息机制的运行原理,先介绍三者之间的协作框架,然后从源码的角度来分析具体的运行机制。一、消息机制概述1.消息机制的简介在Android中使用消息机制,我们首先想到的就是Handler。没错,Handler是And...

weixin_39587238的博客 94

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Handler源码分析

本文出自光临天下的博客,转载出处:https://blog.youkuaiyun.com/qq_41346910/article/details/82841518 这篇博客是一种入门级的但讲的很细,本人能力有限,希望看到大神,发现有不对的地方请联系我,也希望可以和大家在讨论区互动。 本文不管是从哪得到得信息,本人都认真的研究过和测试。包括代码所以说本人技术可能...

weixin_30814223的博客 112

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Android消息处理机制——Handler

1.为什么要使用Handler? 子线程不能更改主线程的UI,在异步消息处理机制中,通过Handler完成从子线程到主线程的切换,完美解决子线程数据请求,主线程更新UI的问题 2.Handler基本原理 主线程里都维护了一个消息对列(message queue),子线程创建消息(Message),通过主线程里的Handler把消息发送到消息队列(message queue),在主线程里还有一个轮循...

qq_40575302的博客 361

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Android 异步任务之Handler解析

1、Handler消息源码流程分析(含手写笔记) 2、Handler(面试详解) 3、Android消息机制Handler的实现原理解析

秦逸轩的博客 387

Android之Handler机制

注:下列所涉及的源码均基于8.0 1. 背景 经历过开发的我们应该都知道当有耗时操作,比如网络请求等的时候要开启线程,在子线程中进行耗时操作,然后耗时操作完后返回到主线程进行UI更新操作。这时候你可能会有疑问了,为什么不能再子线程中操作UI呢?其实这是因为Android的UI控件并不是线程安全的,这就意味着如果子线程能够操作UI的话,就很可能出现多线程并发操作UI导致UI控件出现各种未知的错误...

jsyjst的博客 991

Android Handler 详解

Android开发中经常使用Handler来实现“跨越线程(Activity)更新UI”。本文将从源码角度回答:为什么使用Handler能够跨线程更新UI?为什么跨线程更新UI一定要用Handler? Demo Demo1. 用Handler更新UI 下面这个Demo完全是为了演示“跨...

chongchan9210的博客 183

Android-Handler机制(1)

算法知识点繁多,企业考察的题目千变万化,面对越来越近的“金九银十”,我给大家准备好了一套比较完善的学习方法,希望能帮助大家在有限的时间里尽可能系统快速的恶补算法,通过高效的学习来提高大家面试中算法模块的通过率。这一套学习资料既有文字档也有视频,里面不仅仅有关键知识点的整理,还有案例的算法相关部分的讲解,可以帮助大家更好更全面的进行学习,二者搭配起来学习效果会更好。部分资料展示:有了这套学习资料,坚持刷题一周,你就会发现自己的算法知识体系有明显的完善,离大厂Offer的距离更加近。

2401_84121499的博客 675

Handler消息机制与AsyncTask深度解析-从源码带你看handler

handler在我们Android开发过程中是最长用到的处理消息及其他事务的,其消息机制相信也被大家所熟知 .接下来深入带大家看一下handler的消息机制和AsyncTask的解析 Handler消息机制 Hanlder有四大核心类 Message Hanldre Messagqueue Looper

风离紫竹zhangqiang的博客 4717

Android Handler机制

Handler 即处理器,常用于跨线程通讯:线程A 和线程 B 拥有同一个 handler 对象在线程 A 中使用 handler 的 sendMessage() 方法发送消息在线程 B 中使用 handler 的 handleMessage() 方法处理消息。

xfb的博客 653

Handler 源码分析总结

handle相关一些疑问解答

wuxingdepiaoying1991的专栏 263

Android 线程间通信机制 Handler 的实现原理

在上文中,我们从 Java 层到 Native 层分析了 Handler 的作用的原理。这里我们对这部分内容做一个总结。因为本文中不仅分析了 Java 层的代码,同时分析了 framework 层的代码,所以最好能够结合两边的源码一起看,这样更有助于自己的理解。在上面的文章中,我们给出了一些类的在线的代码链接,在 Google Source 上面,需要 VPN 才能浏览。另外,因为笔者水平有限,难免存在有误和不足的地方,欢迎批评指正。

喜欢Python编程的程序员柚柚呀 1289

Android Loop机制中Looper与handler详细分析

根据以上所说的关系,画一张图:结论:handler的消息分为:同步消息,异步消息,屏障消息。handler的消息发送:消息都发送到了和它绑定的Looper的队列中去了。那么queue一对一looper,looper一对多handler,looper对象保存在所在线程的ThreadLocal中。

jh035的博客 1684
上一篇: Android11 车载 Framework PBAP同步电话簿如何添加姓名全拼和首字母的需求
下一篇: Android 使用maven publish插件发布产物(aar)全过程实践
网络安全-XG
博客等级 码龄5年 1万+粉丝 2752原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值