【Android源码解析】从源码角度深入分析AsyncTask原理

猕猴桃目标检测数据集:1700张多角度实拍图解决产线漏检 目标检测是工业视觉落地的核心技术,其性能高度依赖数据对真实场景的覆盖能力。当面对单类但姿态多变、背景相似、光照无序的农业产线目标(如猕猴桃)时,通用数据集往往失效——模型在平放样本上表现优异,却对侧立、斜倾、堆叠等姿态鲁棒性不足。这类问题本质是‘姿态扰动谱’未被充分建模,导致mAP虚高而产线误检率居高不下。本数据集聚焦水果分拣典型瓶颈,提供1700张VOC+YOLO双格式标注图,覆盖真实产线中的不规则摆放、托盘背景干扰与非均匀光照,专为提升小样本姿态鲁棒性与部署稳定性而设计,适用于YOLOv8等主流框架快速 阅读详情
###一. 什么是AsyncTask? 是Android提供的**轻量级**的异步类,封装了**线程池和handler**。它是个抽象类,使用时需要去继承它,然后去实现异步操作,并反馈异步执行的**结果**。

###二. AsyncTask使用方法
首先先来看个例子,这是之前写过的一个gif图片下载的异步任务。使用AsyncTask要注意它的***三个参数***和***五个方法***。

  1. 三个参数
    第一个,代表执行AsyncTask传入的参数;
    第二个,代表执行后台任务的进度;
    第三个,代表执行完任务返回的结果。
  2. 五个方法
    (1)onPreExecute:在ui线程调用,后台操作执行前调用;经常用于显示一个进度条。
    (2)doInBackground:做的是耗时操作,并返回执行结果。同时,可以在doInBackground中调用publishProgress来发布进度单位。
    (3)onPostExecute:接受执行结果。
    (4)onProgressUpdate:当publishProgress调用完该方法被执行,一般用于控制进度条的进度。
public class GifImageDownLoader extends AsyncTask<String, Void, File> {
    private static final String foldPath = Environment.getExternalStorageDirectory() + "/CTRIP/cache/";
    private ICallBack<File, String> mCallBack;

    public GifImageDownLoader(ICallBack<File, String> callBack) {
        this.mCallBack = callBack;
    }

    @Override
    protected File doInBackground(String... params) {
        String[] url = params[0].split("/");
        String gifName = url[url.length - 1];
        File f = new File(foldPath + gifName);
        if (!f.exists()) {
            f = downLoadGifImage(params[0], gifName);
        }
        return f;
    }

    @Override
    protected void onPostExecute(File f) {
        if (isCancelled() || f == null) {
            mCallBack.fail(null);
            return;
        }
        mCallBack.success(f, null);
    }

    private File downLoadGifImage(String gifUrl, String gifName) {
        File gifImageFile = null;
        InputStream is = null;
        FileOutputStream fos = null;
        try {
            URL downLoadUrl = new URL(gifUrl);
            HttpURLConnection conn = (HttpURLConnection) downLoadUrl.openConnection();
            conn.setConnectTimeout(5000);
            conn.setRequestMethod("GET");
            if (conn.getResponseCode() == 200) {
                File fold = new File(Environment.getExternalStorageDirectory() + "/CTRIP/cache");
                if (!fold.exists()) {
                    fold.mkdirs();
                }
                is = conn.getInputStream();
                gifImageFile = new File(foldPath, gifName);
                fos = new FileOutputStream(gifImageFile);
                int len = 0;
                byte[] buffer = new byte[1024];
                while ((len = is.read(buffer)) != -1) {
                    fos.write(buffer, 0, len);
                }
                fos.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
                if (fos != null) {
                    fos.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return gifImageFile;
    }

}

###三. AsyncTask内部原理
Android主线程肩负绘制UI界面和即使响应用户操作的重任,所以为了避免用户点击按钮没有反应,应该把耗时操作放在子线程进行。

  1. AsyncTask本质是一个静态的线程池,其子类实现的异步任务都提交到静态线程池中进行。
  2. 线程池的工作线程执行doInBackground(mParams)方法执行异步任务。
  3. 当任务状态改变后,子线程向UI线程发送消息,AsyncTask内部的handler相应这些消息,并调用相关回调函数。

###四. 线程池ThreadPoolExecutor
创建线程池一般不直接new一个线程池对象,因为需要配置一堆东西,我们来看下其构造方法:
这里写图片描述
所以官方也不推荐我们这样创建线程池,而是推荐使用Executors的工厂方法来创建线程池,Executors是官方提供的一个工厂类,它里面封装了众多功能的线程池,从而使得我们创建线程池非常简便,主要提供了五种线程池:
#####1. newFixedThreadPool()
创建一个固定线程数量的线程池,该线程池中的线程数量都不变,即不会创建新的线程,也不会销毁已经创建好的线程,自始至终都是那几个固定的线程工作。
如果有空闲线程则处理任务,如果没有则将任务放到一个队列中,一旦线程空闲了则按FIFO的方式处理队列中的任务。

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
}

#####2. newCachedThreadPool()
该线程池中的线程数量不固定,可根据实际情况调整。
如果有新任务提交,当没有空闲线程则创建新线程,如果有空闲线程则复用该空闲线程,当空闲线程空闲时间超过配置的等待时间则被销毁。

 public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
}

#####3. newSingleThreadPool()
只有一个线程的线程池。

public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
}

#####4. newScheduledThreadPool()
可定时执行某任务的线程池。

public static ScheduledExecutorService newScheduledThreadPool(
            int corePoolSize, ThreadFactory threadFactory) {
        return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
}

#####5. newSingleThreadScheduledPool()
只有一个线程的可定时执行某任务的线程池。

可以看到工厂方法最终都是通过ThreadPoolExecutor来创建线程池。在它的构造方法的参数中,最重要的是BlockingQueue任务队列,不同线程池的任务队列实现方法肯定不同。
而线程池的使用也很简单,当创建好线程池后,只需要调用其execute方法即可。

####AsyncTask源码解析
AsyncTask的源码其实非常短,只有700多行。我们先来看AsyncTask的构造方法。
#####AsyncTask构造方法

public AsyncTask() {
        mWorker = new WorkerRunnable<Params, Result>() {
            public Result call() throws Exception {
                mTaskInvoked.set(true);
                Result result = null;
                try {
                    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                    //noinspection unchecked
                    result = doInBackground(mParams);
                    Binder.flushPendingCommands();
                } catch (Throwable tr) {
                    mCancelled.set(true);
                    throw tr;
                } finally {
                    postResult(result);
                }
                return result;
            }
        };

        mFuture = new FutureTask<Result>(mWorker) {
            @Override
            protected void done() {
                try {
                    postResultIfNotInvoked(get());
                } catch (InterruptedException e) {
                    android.util.Log.w(LOG_TAG, e);
                } catch (ExecutionException e) {
                    throw new RuntimeException("An error occurred while executing doInBackground()",
                            e.getCause());
                } catch (CancellationException e) {
                    postResultIfNotInvoked(null);
                }
            }
        };
    }
  1. workRunnable是一个Callable,大家可能对Callable不熟悉,它其实跟Runnable使用非常像,只不过Callable有返回值而Runnable没有。
  2. FutureTask是Callable的包装类。
    ####execute方法
    execute方法其实执行的是executeOnExecutor方法。
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
        return executeOnExecutor(sDefaultExecutor, params);
}
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
            Params... params) {
        if (mStatus != Status.PENDING) {
            switch (mStatus) {
                case RUNNING:
                    throw new IllegalStateException("Cannot execute task:"
                            + " the task is already running.");
                case FINISHED:
                    throw new IllegalStateException("Cannot execute task:"
                            + " the task has already been executed "
                            + "(a task can be executed only once)");
            }
        }

        mStatus = Status.RUNNING;

        onPreExecute();

        mWorker.mParams = params;
        exec.execute(mFuture);

        return this;
}

可以看到executeOnExecutor传入的第一个参数是sDefaultExecutor,这是一个线程池。我们稍后来分析这个线程池,我们先来看下executeOnExecutor里都做了什么。

  1. 首先是判断AsyncTask当前的执行状态,只有当前状态是Status.PENDING才可继续使用;
  2. 接着设置当前状态为RUNNING状态。
  3. 然后调用onPreExecute方法。
  4. 接着为mWorker设置参数,并执行该任务。
    #####AsyncTask中线程池SerialExecutor
private static class SerialExecutor implements Executor {
        final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
        Runnable mActive;

        public synchronized void execute(final Runnable r) {
            mTasks.offer(new Runnable() {
                public void run() {
                    try {
                        r.run();
                    } finally {
                        scheduleNext();
                    }
                }
            });
            if (mActive == null) {
                scheduleNext();
            }
        }

        protected synchronized void scheduleNext() {
            if ((mActive = mTasks.poll()) != null) {
                THREAD_POOL_EXECUTOR.execute(mActive);
            }
        }
    }

可以看到SerialExecutor就是将异步任务一个一个放入队列里,然后再去执行。不过还需要注意的是execute方法加上了synchronized修饰,从而保证AsyncTask中的任务是串行执行的。
###五. 内部handler
当任务执行完通过internalHandler讲执行结果同步给主线程。

private static class InternalHandler extends Handler {
        public InternalHandler() {
            super(Looper.getMainLooper());
        }

        @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
        @Override
        public void handleMessage(Message msg) {
            AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
            switch (msg.what) {
                case MESSAGE_POST_RESULT:
                    // There is only one result
                    result.mTask.finish(result.mData[0]);
                    break;
                case MESSAGE_POST_PROGRESS:
                    result.mTask.onProgressUpdate(result.mData);
                    break;
            }
        }
}

###六. 最后
以上就是我对AsyncTask源码的分析,后续当我有新的理解时还会继续更新。至于为什么想到要去看AsyncTask的源码了呢?主要是因为最近想要改进一下我们的缓存机制,希望能在合适的时机清理一下缓存,我们用AsyncTask比较多,也知道它是封装了线程池和handler,但具体怎么实现的还真没有系统地读过。
好了,时间不早了,现在是夜里十二点十五,大家晚安。如有任何疑问可以邮件联系我zhshan@ctrip.com。

Android-详细解读AsyncTask的黑暗面以及一种替代方案 详细解读AsyncTask的黑暗面以及一种替代方案 立即下载

相关推荐

Android AsyncTask 源码解析

代码为博客的示例代码,有问题请博客中留言:http://blog.youkuaiyun.com/lmj623565791/article/details/38614699

android之AsyncTask原理分析

通过名字就可以知道,AsyncTask主要用于处理android中的异步任务。但是通过源码,我们可以看到它的实现其实还是依赖于Handler的异步消息处理机制。现在我们先来学习它的使用方式,然后再研究源码。 一.AsyncTask的基本用法: AsyncTask是一个抽象类,在之类继承它时,必须指定三个泛型参数,这三个参数的用途如下: 1. 在执行AsyncTask时需要传入的参数,可用

sjz4860402的专栏 3399

android AsyncTask详细介绍

AsyncTask和Handler对比 1 ) AsyncTask实现的原理,和适用的优缺点 AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程. 使用的优点: 简单,快捷 过程可控  使用的缺点: 在使用多个异步操作和并需要进行Ui变更时,就变得复杂起来. 2 )Handler异步实现的原理和适用的优缺点 在Handler 异步实现时,涉及到 Handler, Looper, Message,Thread四个对象,实现异步的流

Android中的AsyncTask原理

Android中的AsyncTask原理: 在Android开发中,当通过线程去执行耗时的任务,并且在操作完以后可能还会更新UI时,通常还会用Handler类来更新UI线程。总体来说,实现简单,但是如果有多个任务同时执行时则会显得代码臃肿。Android提供了AsyncTask,它使得异步任务实现起来更加简单,代码更简介。 AsyncTask的定义: public abstract class ...

手写我对你的温柔 2172

机器人开发路线

通过这个路线图,你可以在6个月内完成从原型到试产的全流程。建议初期采用敏捷开发模式,每两周迭代一个核心功能模块。在硬件集成遇到瓶颈时,推荐参考。

woody218的博客 745

ICNN实现入侵检测的思路与源码(CIC-IDS-2017)

基于ICNN实现入侵检测,可用于现实网络

t1274171989的博客 8415

Android 异步任务类之AsyncTask 完全解析

Android 异步任务类之AsyncTask 完全解析

weixin_42504805的博客 2366

Wireshark抓包实战:5个CTF比赛中高频出现的流量分析技巧(附真实案例)

本文分享了Wireshark在CTF比赛和实战渗透中的五个核心流量分析技巧。内容涵盖从宏观统计概览锁定可疑目标、深度解析ICMP与HTTP等协议、追踪重组完整会话流,到利用字符串搜索和命令行工具进行自动化分析。掌握这些高阶技巧能显著提升分析海量网络流量的效率与精准度。

rrr55的博客 261

Android基础知识(十一):AsyncTask原理与使用简介

Android异步操作工具AsyncTask原理与使用简介 在Android应用开发的过程必须遵循单线程模型的原则:Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。 单线程模型有2条法则: 不要阻塞UI线程 确保只在UI线程中访问Android UI工具包 一、Android异步操作工具 Android提供了几种在其他线程中访问UI线程的方法: Activity.r...

weixin_38196407的博客 448

保姆级教程:从AD导出Gerber到HFSS 3D Layout导入,搞定PCB电磁仿真全流程

本文提供从Altium Designer导出Gerber文件到Ansys HFSS 3D Layout导入的完整PCB电磁仿真流程指南。详细讲解Gerber文件导出设置、HFSS中的3D模型重建技巧,以及电磁仿真中的常见问题解决方案,帮助工程师高效完成高速电路和射频设计的性能验证。

weixin_30379531的博客 709

电容式三点式振荡电路/电感式三点振荡电路基础知识及Multisim电路仿真

摘要:三极管振荡电路利用放大特性与正反馈实现自激振荡,需满足巴克豪森条件(增益≥1,相位匹配)。核心由放大级、反馈网络、选频网络和稳幅环节构成。主要分为三类:1)LC/RC正弦波振荡电路(如电容三点式、电感三点式),输出高频/低频正弦波;2)多谐振荡电路,通过电容充放电产生方波;3)张弛振荡电路,生成锯齿波等。设计需关注相位匹配、增益控制和元件适配。LC振荡频率由谐振参数决定,RC振荡由时间常数控制。稳幅机制通过非线性或主动元件维持等幅输出。该电路在信号发生、时钟源等领域有广泛应用。

XU157303764的博客 2038

android ayntask原理,AsyncTask解析

目录:* 1.AsyncTask介绍* 2.AsyncTask中提供了四个核心方法* 3.AsyncTask的注意事项* 4.AsyncTask实现原理* 5.AsyncTask执行的串行和并发AsyncTask介绍:简介:AsyncTask是一个轻量级的异步任务类,它可以在线程池中后台执行任务,可以将执行的进度和执行完成之后的结果返回到UI线程中;AsyncTask是一个抽象的泛型类,其有三个泛...

weixin_42682754的博客 182

Python爬虫实战:实时爬取东方财富网股票行情

东方财富网实时行情(价格、涨跌幅、成交量等)K线图、分时图、技术指标市盈率、换手率、总市值等指标相比某些收费API,东方财富网页端接口不需要登录、免费、响应快、封装清晰,适合爬虫实践。东方财富网股票数据接口分析实时数据抓取与字段提取数据结构化处理自动化批量抓取多线程加速采集数据可视化展示支持存储为CSV/Excel/数据库。

2201_76125261的博客 1万+

Android AsyncTask完全解析,带你从源码的角度彻底理解

我们都知道,Android UI是线程不安全的,如果想要在子线程里进行UI操作,就需要借助Android的异步消息处理机制。之前我也写过了一篇文章从源码层面分析了Android的异步消息处理机制,感兴趣的朋友可以参考 Android Handler、Message完全解析,带你从源码的角度彻底理解 。 不过为了更加方便我们在子线程中更新UI元素,Android从1.5版本就引入了一个AsyncTask类,使用它就可以非常灵活地在UI线程和子线程之间自由切换。同时,它也是我们本篇文章的主角。 AsyncTas

郭霖的专栏 11万+

UNet + Shuffle Attention:一种轻量高效的医学图像分割注意力机制

本文提出了一种轻量高效的医学图像分割方法,将Shuffle Attention模块嵌入UNet的上采样路径中。Shuffle Attention通过通道分组注意力机制增强关键特征,同时保持计算轻量化。该方法在上采样后应用注意力模块,有效融合高层语义与低层细节,计算开销小且易于部署。实验表明,该模型在保持UNet原有优势的基础上,通过注意力机制提升了特征聚焦能力,适用于多种图像分割任务。未来可进一步结合空间注意力或Transformer模块以增强模型性能。

Henry的博客 240

Open Dynamics Engine(ODE)物理引擎基础教程(I)——特点介绍

下一教程 Open Dynamics Engine(ODE)物理引擎基础教程(II)——相关概念 (在这一教程中将学习刚体、关节、碰撞的概念在ODE中的特点) 本文结构引言介绍特点使用ODE总结 引言 本文翻译自ODE官方教程英文版,有些地方增加了自己的理解。这一节介绍ODE的相关概念。 基础教程英文原版链接【http://ode.org/wiki/index.php?title=Manua...

腿足机器人领域 1678

深入分析AsyncTask

什么是AsyncTask ==AsyncTask 即 asynchronous task,异步任务==。AsyncTask实际上是围绕Thread和Handler设计的一个辅助类,在内部是对Thread和Handler的一种封装。AsyncTask的异步体现在由后台线程进行运算(访问网络等比较耗时的操作),然后将结果发布到用户界面上来更新UI,使用AsyncTask使得我不用操作Thread和Han

JasonGaoH的专栏 1970

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Android AsyncTask完全解析,站在源码的角度上

我们都知道,Android UI是线程不安全的,如果想要在子线程里进行UI操作,就需要借助Android的异步消息处理机制。也就是Handler,Message, Thread。 不过为了更加方便我们在子线程中更新UI元素,Android从1.5版本引入了AsyncTask类,使用它我们可以更灵活方便的实现子线程更新UI元素。 AsyncTask基本用法 首先来看一下AsyncTas

wsyjx22的专栏 717

IDEA的使用指南

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

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

android之Futuretask、Timer、AsyncTask的使用及原理解析

之前用写过这么一篇文章,但是写的很简单(那时候想的只是给自己做个笔记),但是后来想想还是有必要写的详细些,所以就把这前那篇删了,重写整理除了这篇文章。 还是先给出参考的博文地址: Java 并发专题 :FutureTask 实现预加载数据 在线看电子书、浏览器浏览网页等 Java并发编程:Callable、Future和FutureTask Java 并发专题 : Timer的缺陷

ShanQuanQiang的专栏 2906

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

源码分析之AsyncTask

AsyncTask在Android中是很常用的异步线程,那么AsyncTask和Thread有什么区别呢?这里将从源码角度深入理解AsyncTask的设计和工作原理 这里的AsyncTask基于SDK-25 分析知识准备 首先我们来看一个生产者与消费者模型的例子 public class ThreadTest { //产品 static class ProductObject{ pub...

cj5785 1910

Android面试必备——AsyncTask源码解析

AsyncTask是Android中常用的异步任务解决方案,在面试中面试官经常会问到有关AsyncTask相关的点,很多人只知道如何去用AsyncTask,没有深入过源码理解其原理,这在面试的时候往往对自己不利,本文从源码角度解读AsyncTask的原理及使用,相信读完本文你就可以很好地应对Android面试中有关AsyncTask的问题。 首先,AsyncTask是一个抽象类,我们使用的时候需要...

ai-exception的博客 1135

Android 从源码的角度带你完全解析AsyncTask

AsyncTask()解析 public AsyncTask() { mWorker = new WorkerRunnable<Params, Result>() { public Result call() throws Exception { mTaskInvoked.set(true);

一口仨馍 1748
上一篇: 【Android 编程框架】网络缓存框架重构
下一篇: 【Android 设计模式】Builder模式
Colin_Mindset
博客等级 码龄12年 159粉丝 105原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值