当前位置: 首页 > news >正文

Android后台任务(HandlerThread、AsyncTask、IntentService)

线程只是最基本的应用,在复杂的场景下使用Thread代码可读性会变的很多差而且也容易出错。 android为了简化开发者的工作量,提供了一些更容易使用的封装。

HandlerThread

为了让Handler在非主线程工作,可以使用HandlerThread。 如题使用如下:

    Handler handler;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        HandlerThread handlerThread = new HandlerThread("backThread",Process.THREAD_PRIORITY_BACKGROUND);
        handlerThread.start();
        handler = new Handler(handlerThread.getLooper());
    }
复制代码

使用HandlerThread的Looper之后,Handler就是在HandlerThread所在线程中处理消息了。 其实HandlerThread就是新建了线程,然后调用了Looper.prepare();Looper.loop();

AsyncTask

AsyncTask 现在使用的人已经不多了,它也是一个使用很简单的后台任务类,开发者不需要关注Thread和Handler就能在后台线程完成轻量级和时间较短的任务,并且最后在UI线程更新。

/*第一个为入参类型
 *第二个是进度类型
 *第三个是结果类型
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
     protected Long doInBackground(URL... urls) {
         int count = urls.length;
         long totalSize = 0;
         for (int i = 0; i < count; i++) {
             totalSize += Downloader.downloadFile(urls[i]);
             publishProgress((int) ((i / (float) count) * 100));
             // Escape early if cancel() is called
             if (isCancelled()) break;
         }
         return totalSize;
     }

     protected void onProgressUpdate(Integer... progress) {
         setProgressPercent(progress[0]);
     }

     protected void onPostExecute(Long result) {
         showDialog("Downloaded " + result + " bytes");
     }
 }
复制代码

下面可以看方法在哪个线程调用 :

    @WorkerThread
    protected abstract Result doInBackground(Params... params);

    @MainThread
    protected void onPreExecute() {
    }
    @MainThread
    protected void onPostExecute(Result result) {
    }

    @MainThread
    protected void onProgressUpdate(Progress... values) {
    }

复制代码

其实AsyncTask有一个包含一个静态的线程池,最小同时运行两个线程,最多4个线程。

    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    // We want at least 2 threads and at most 4 threads in the core pool,
    // preferring to have 1 less than the CPU count to avoid saturating
    // the CPU with background work
    private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
    private static final int KEEP_ALIVE_SECONDS = 30;

    private static final ThreadFactory sThreadFactory = new ThreadFactory() {
        private final AtomicInteger mCount = new AtomicInteger(1);

        public Thread newThread(Runnable r) {
            return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
        }
    };

    private static final BlockingQueue<Runnable> sPoolWorkQueue =
            new LinkedBlockingQueue<Runnable>(128);

    /**
     * An {@link Executor} that can be used to execute tasks in parallel.
     */
    public static final Executor THREAD_POOL_EXECUTOR;

    static {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
                sPoolWorkQueue, sThreadFactory);
        threadPoolExecutor.allowCoreThreadTimeOut(true);
        THREAD_POOL_EXECUTOR = threadPoolExecutor;
    }
复制代码

其中还有一个handler用于更新UI线程。

    private static Handler getMainHandler() {
        synchronized (AsyncTask.class) {
            if (sHandler == null) {
                sHandler = new InternalHandler(Looper.getMainLooper());
            }
            return sHandler;
        }
    }

    private Handler getHandler() {
        return mHandler;
    }
复制代码

由于都是静态的,所以其实所有的AsyncTask都是公用这个线程池和Handler。 AsyncTask使用起来也很简单,但是有一些限制,只能在UI线程实例化和调用。

new DownloadFilesTask().execute(url1,url2,url3);
复制代码

IntentService

IntentService是为了处理异步任务而对Service的封装。 其实原理也很简单。

    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);
        }
    }

    @Override
    public void onCreate() {
        // TODO: It would be nice to have an option to hold a partial wakelock
        // during processing, and to have a static startService(Context, Intent)
        // method that would launch the service & hand off a wakelock.

        super.onCreate();
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }
    @Override
    public void onStart(@Nullable Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }
复制代码

就是在Service的OnCreate里创建了一个HandlerThread,然后把需要处理的Intent发送到这个Handler在后台线程中处理并且完毕后调用stopSelf关闭服务。

使用上和Service一样,就是需要重写onHandleIntent方法。

转载于:https://juejin.im/post/5c8753bc5188257e453c6400

相关文章:

  • 为什么开发人员必须要了解数据库锁?
  • 前嗅ForeSpider脚本教程:基本语句
  • Redis保证事务一致性,以及常用的数据结构
  • LNMP基础知识及简单搭建(用于个人学习与回顾)
  • Gnu/Linux 链接XServer方法
  • vue中添加favicon.ico
  • 面试篇三
  • SAP开源Java SCA工具,提供静态代码安全性测试功能
  • 最快1天搭建短视频APP!阿里云短视频解决方案上线
  • CSS3 属性
  • 《重新定义团队》读书笔记及阅读感想2600字
  • Kubernetes — 作业副本与水平扩展
  • BootStack 权限管理平台体验环境正式上线了
  • Windows Server 2016 检查更新时,错误代码8024401C 的解决方案
  • “十年磨一剑”--有赞的HBase平台实践和应用之路 ...
  • [case10]使用RSQL实现端到端的动态查询
  • [分享]iOS开发 - 实现UITableView Plain SectionView和table不停留一起滑动
  • “大数据应用场景”之隔壁老王(连载四)
  • 【Leetcode】104. 二叉树的最大深度
  • 【Redis学习笔记】2018-06-28 redis命令源码学习1
  • 77. Combinations
  • CEF与代理
  • docker python 配置
  • ECMAScript入门(七)--Module语法
  • Hibernate【inverse和cascade属性】知识要点
  • Iterator 和 for...of 循环
  • javascript 总结(常用工具类的封装)
  • leetcode-27. Remove Element
  • mac修复ab及siege安装
  • Objective-C 中关联引用的概念
  • Redis 懒删除(lazy free)简史
  • vuex 笔记整理
  • 浮现式设计
  • 简单基于spring的redis配置(单机和集群模式)
  • 使用阿里云发布分布式网站,开发时候应该注意什么?
  • 微信小程序上拉加载:onReachBottom详解+设置触发距离
  • LIGO、Virgo第三轮探测告捷,同时探测到一对黑洞合并产生的引力波事件 ...
  • 国内唯一,阿里云入选全球区块链云服务报告,领先AWS、Google ...
  • 好程序员大数据教程Hadoop全分布安装(非HA)
  • 基于django的视频点播网站开发-step3-注册登录功能 ...
  • 如何在招聘中考核.NET架构师
  • ​​​​​​​Installing ROS on the Raspberry Pi
  • #我与Java虚拟机的故事#连载15:完整阅读的第一本技术书籍
  • (3)STL算法之搜索
  • (4)STL算法之比较
  • (二)基于wpr_simulation 的Ros机器人运动控制,gazebo仿真
  • (三)Honghu Cloud云架构一定时调度平台
  • (三)模仿学习-Action数据的模仿
  • (深度全面解析)ChatGPT的重大更新给创业者带来了哪些红利机会
  • (图)IntelliTrace Tools 跟踪云端程序
  • (原+转)Ubuntu16.04软件中心闪退及wifi消失
  • (转)Sublime Text3配置Lua运行环境
  • .NET : 在VS2008中计算代码度量值
  • .NET CF命令行调试器MDbg入门(二) 设备模拟器
  • .NET CORE 第一节 创建基本的 asp.net core