转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/52847872
本文出自【赵彦军的博客】

  • 概述
  • 封装尝试
  • Handler优化
  • 线程优化
  • 框架使用
  • 参考资料

概述

在Android中会使用异步任务来处理耗时操作,避免出现界面卡顿的问题,当然到目前为止可以使用的异步任务框架有很多,比如:

  • 直接 new Thread()
  • 用Android自带的AsyncTask
  • 用RxJava
  • 等等

    今天我们就来自己尝试写一个异步任务处理框架,代码的设计思路参考AsyncTask

封装尝试

既然是异步的框架,那么肯定是在子线程中,所以第一步我们用自定义的ThreadTask继承Thread. 并且重写里面的run方法。

package com.zyj.app;/*** Created by ${zyj} on 2016/10/17.*/public class ThreadTask extends Thread {@Overridepublic void run() {super.run();}
}

然后子线程需要把处理结果回调给主线程,我们需要定义3个方法:

  • onStart 任务开始之前调用,运行在主线程。可以做显示进度条或者加载动画。
  • onDoInBackground 异步任务执行,运行在子线程。可以做耗时操作。
  • onResult 异步任务处理的结果,运行在主线程。

    onDoInBackground这个方法是要在子类中实现的,所以要写成抽象的方法,那么ThreadTask类自然也要写成抽象类。同时这个方法会返回异步处理结果,这个结果的类型需要写成泛型,以便在子类中灵活运用。

package com.zyj.app;import android.support.annotation.MainThread;
import android.support.annotation.WorkerThread;/*** Created by ${zyj} on 2016/10/17.*/public abstract class ThreadTask<T> extends Thread  {@Overridepublic void run() {super.run();}/*** 任务开始之前调用,运行在主线程*/@MainThreadpublic void onStart(){ }/*** 子线程中调用,运行在子线程* @return*/@WorkerThreadpublic abstract T onDoInBackground() ;/*** 子线程返回的结果,运行在主线程* @param t*/@MainThreadpublic void onResult( T t ){ }
}

另外子线程和主线程通信我们用的是Handler。Handler的初始化工作放在ThreadTask构造函数中完成。

    private Handler handler ;public ThreadTask(){handler = new Handler( Looper.getMainLooper()){@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);//在这里接收子线程发过来的消息}} ;}

最后还需要一个execute() 方法启动线程。在启动的前一刻最好调用Onstart方法。

    /*** 开始执行*/public void execute(){onStart();start();}

最后一个完整的ThreadTask类是这样的

package com.zyj.app;import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.annotation.MainThread;
import android.support.annotation.WorkerThread;/*** Created by ${zyj} on 2016/10/17.*/public abstract class ThreadTask<T> extends Thread  {private Handler handler ;public ThreadTask(){handler = new Handler( Looper.getMainLooper()){@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);//在这里接收子线程发过来的消息onResult((T) msg.obj);}} ;}@Overridepublic void run() {super.run();Message message = Message.obtain() ;message.obj = onDoInBackground() ;handler.sendMessage( message ) ;}/*** 任务开始之前调用,运行在主线程*/@MainThreadpublic void onStart(){ }/*** 子线程中调用,运行在子线程* @return*/@WorkerThreadpublic abstract T onDoInBackground() ;/*** 子线程返回的结果,运行在主线程* @param t*/@MainThreadpublic void onResult( T t ){ }/*** 开始执行*/public void execute(){onStart();start();}
}

如何使用我们写好的框架?

new ThreadTask<String>(){@Overridepublic void onStart() {super.onStart();Log.d( "ThreadTask " , "onStart线程:" + Thread.currentThread().getName() ) ;}@Overridepublic String onDoInBackground() {Log.d( "ThreadTask " , "onDoInBackground线程: " + Thread.currentThread().getName() ) ;//模拟耗时操作try {Thread.sleep( 3000 );} catch (InterruptedException e) {e.printStackTrace();}return "结果返回了";}@Overridepublic void onResult(String s) {super.onResult(s);Log.d( "ThreadTask " , "onResult线程: " + Thread.currentThread().getName()  + " 结果:" + s ) ;}}.execute();

运行的结果:

ThreadTask: onStart线程:main
ThreadTask: onDoInBackground线程: Thread-229
ThreadTask: onResult线程: main 结果:结果返回了

Handler优化

到目前为止我们的框架初步就封装好了,但是有没有缺点呢,肯定是有的。首先每次创建一个ThreadTask的时候都会创建一个Handler,这显然不是我们想看到的。

  • 要保证Handler的实例的唯一性,可以用单例模式来获取Handler
    /*** 单例模式,保证handler只有一个实例* @return*/private static Handler getHandler(){if ( handler == null ){synchronized ( MHandler.class ){if ( handler == null ){handler= new MHandler( Looper.getMainLooper()) ;}}}return handler ;}
  • MHandler是我们自定义的一个Handler类
    private static class MHandler extends Handler {public MHandler( Looper looper ){super( looper );}@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);//在这里接收子线程发过来的消息ResultData resultData = (ResultData) msg.obj;resultData.threadTask.onResult( resultData.data );}}
  • ResultData是一个消息实体
  /*** handler发送数据的实体* @param <Data>*/private static class ResultData<Data>{ThreadTask threadTask ;Data data ;public ResultData( ThreadTask threadTask  ,Data data  ){this.threadTask = threadTask ;this.data = data ;}}
  • 一个完整的代码实例
package com.zyj.app;import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.annotation.MainThread;
import android.support.annotation.WorkerThread;/*** Created by ${zyj} on 2016/10/17.*/public abstract class ThreadTask<T> extends Thread  {private static Handler handler ;public ThreadTask(){}@Overridepublic void run() {super.run();Message message = Message.obtain() ;message.obj = new ResultData<T>( this , onDoInBackground() ) ;getHandler().sendMessage( message ) ;}/*** 任务开始之前调用,运行在主线程*/@MainThreadpublic void onStart(){ }/*** 子线程中调用,运行在子线程* @return*/@WorkerThreadpublic abstract T onDoInBackground() ;/*** 子线程返回的结果,运行在主线程* @param t*/@MainThreadpublic void onResult( T t ){ }/*** 开始执行*/public void execute(){onStart();start();}/*** 单例模式,保证handler只有一个实例* @return*/private static Handler getHandler(){if ( handler == null ){synchronized ( MHandler.class ){if ( handler == null ){handler= new MHandler( Looper.getMainLooper()) ;}}}return handler ;}private static class MHandler extends Handler {public MHandler( Looper looper ){super( looper );}@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);//在这里接收子线程发过来的消息ResultData resultData = (ResultData) msg.obj;resultData.threadTask.onResult( resultData.data );}}/*** handler发送数据的实体* @param <Data>*/private static class ResultData<Data>{ThreadTask threadTask ;Data data ;public ResultData( ThreadTask threadTask  ,Data data  ){this.threadTask = threadTask ;this.data = data ;}}
}

到现在已经解决了Handler多次创建的问题,那么这个ThreadTask本质上还是新建线程来运行异步任务,为了避免不断的创建线程,所以还需要一个线程池。

线程优化

  • 首选定义一个线程池,默认最大10个线程。
    /*** 线程池,创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。*/private static ExecutorService executorService = Executors.newFixedThreadPool( 15 ) ;
  • 修改run()方法。
    private void run() {executorService.execute(new Runnable() {@Overridepublic void run() {Message message = Message.obtain() ;message.obj = new ResultData<T>( ThreadTask.this , onDoInBackground() ) ;getHandler().sendMessage( message ) ;}});}
  • execute() 方法
    /*** 开始执行*/public void execute(){onStart();run();}
  • 完整的代码实例
package com.zyj.app;import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.annotation.MainThread;
import android.support.annotation.WorkerThread;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** Created by ${zyj} on 2016/10/17.*/public abstract class ThreadTask<T>  {private static Handler handler ;/*** 线程池,创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。*/private static ExecutorService executorService = Executors.newFixedThreadPool( 15 ) ;public ThreadTask(){}private void run() {executorService.execute(new Runnable() {@Overridepublic void run() {Message message = Message.obtain() ;message.obj = new ResultData<T>( ThreadTask.this , onDoInBackground() ) ;getHandler().sendMessage( message ) ;}});}/*** 任务开始之前调用,运行在主线程*/@MainThreadpublic void onStart(){ }/*** 子线程中调用,运行在子线程* @return*/@WorkerThreadpublic abstract T onDoInBackground() ;/*** 子线程返回的结果,运行在主线程* @param t*/@MainThreadpublic void onResult( T t ){ }/*** 开始执行*/public void execute(){onStart();run();}/*** 单例模式,保证handler只有一个实例* @return*/private static Handler getHandler(){if ( handler == null ){synchronized ( MHandler.class ){if ( handler == null ){handler= new MHandler( Looper.getMainLooper()) ;}}}return handler ;}private static class MHandler extends Handler {public MHandler( Looper looper ){super( looper );}@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);//在这里接收子线程发过来的消息ResultData resultData = (ResultData) msg.obj;resultData.threadTask.onResult( resultData.data );}}/*** handler发送数据的实体* @param <Data>*/private static class ResultData<Data>{ThreadTask threadTask ;Data data ;public ResultData( ThreadTask threadTask  ,Data data  ){this.threadTask = threadTask ;this.data = data ;}}
}

框架使用

  • 方式1
        new ThreadTask<String>(){@Overridepublic String onDoInBackground() {return "我是线程";}}.execute();
  • 方式2
    new MyTask().execute();class MyTask extends ThreadTask<String> {@Overridepublic void onStart() {super.onStart();}@Overridepublic String onDoInBackground() {try {//模拟耗时操作Thread.sleep( 2000);} catch (InterruptedException e) {e.printStackTrace();}return "ThreadTask" ;}@Overridepublic void onResult(String s) {super.onResult(s);}}

参考资料

【1】Android AsyncTask 深度理解、简单封装、任务队列分析、自定义线程池
【2】Android 自定义线程池的实战
【3】Java 单例模式
【4】Android Handler、Loop 的简单使用
【5】Android 更新UI的几种方式

Android 从零开始打造异步处理框架相关推荐

  1. android 学习随笔十二(网络:使用异步HttpClient框架)

    使用异步HttpClient框架发送get.post请求 在https://github.com/  搜索 asyn-http https://github.com/search?utf8=✓& ...

  2. 从零开始打造自己的PHP框架――第2章

    目标 本篇,我们来实现加载控制器.数据查询和页面渲染. 原文地址:http://www.voidking.com/2017/... 加载控制器 控制器 在app目录下,新建ctrl目录,ctrl目录下 ...

  3. [android] 异步http框架与实现原理

    介绍github上的异步http框架android-async-http loopj开发 获取AsyncHttpClient对象,通过new 调用AsyncHttpClient对象的get(url,r ...

  4. 树莓派 + Home Assistant + HomeKit 从零开始打造个人智能家居系统 篇二:初步配置 Home Assistant 并连接小米设备与 HomeKit

    树莓派 + Home Assistant + HomeKit 从零开始打造个人智能家居系统 篇二:初步配置 Home Assistant 并连接小米设备与 HomeKit 通过本篇教程,你将完成对 H ...

  5. 【秒杀系统】从零开始打造简易秒杀系统(一):防止超卖

    前言 大家好,好久不发文章了.(快一个月了- -)最近有很多学习的新知识想和大家分享,但无奈最近项目蛮忙的,很多文章写了一半搁置在了笔记里,待以后慢慢补充发布. 本文主要是通过实际代码讲解,帮助你一步 ...

  6. 2017 Android GitHub常用热门开源框架汇总

    现在 GitHub 上流行的开源库极大地节省了开发者从 0 开发的时间,很多公司和个人都在 GitHub 上开源自己的项目,今天我们就来整理一下 Android 开发中一些非常流行的库,也是我们必须掌 ...

  7. AsyncQueryHandler 异步查询框架

    AsyncQueryHandler简介: 异步的查询操作帮助类,可以处理增删改(ContentProvider提供的数据) 使用场景: 在一般的应用中可以使用ContentProvider去操作数据库 ...

  8. Android之AsyncTask异步任务详解总结

    Android 多线程----AsyncTask异步任务详解 [正文] 本文将讲解一下Android的多线程的知识,以及如何通过AsyncTask机制来实现线程之间的通信. 一.Android当中的多 ...

  9. Android Glide图片加载框架(三)缓存机制

    文章目录 一.缓存简介 二.缓存用法 内存缓存方式 磁盘缓存方式 三.缓存KEY 四.内存缓存 内存缓存流程 五.磁盘缓存 磁盘缓存流程 Android Glide图片加载框架系列文章 Android ...

最新文章

  1. 【拓扑排序】【bitset】Gym - 101128A - Promotions
  2. 人脸和性别识别(基于OpenCV)
  3. 北大OJ百练——3179:最长单词(C语言)
  4. centos6查看java命令_centos6.5下常见命令和操作
  5. java nio与io_Java NIO和IO的区别(转)
  6. 备忘:phalcon的坑
  7. java 并发测试main方法_java并发编程test之synchronized测试
  8. saltstack mysql_saltstack学习五:return及入库_MySQL
  9. 代码管理工具TortoiseGit配置(GIT的客户端)
  10. ebpf_exporter - Prometheus exporter for custom eBPF metrics
  11. 监视和调整Linux网络协议栈:接收数据
  12. Infer.NET——为热爱概率的人准备的库
  13. 麓山滨江2021高考成绩查询,长沙2021高考成绩排名榜单,长沙各高中高考成绩喜报...
  14. 在微型计算机中r o m是什么,微机原理试题一
  15. 学计算机的该不该参加培训机构
  16. 完美收官!Fortinet Accelerate 2022中国站在北京落幕
  17. 自然语言生成技术现状调查:核心任务、应用和评估(2)
  18. 密码学基础:Base64编码
  19. 华为FreeBuds SE耳机突然没有声音了是怎么回事?
  20. 拼多多关键词搜索商品接口,拼多多关键词搜索列表接口,宝贝详情页接口,关键词取商品列表接口

热门文章

  1. mybatis mysql crud_Mybatis实现CRUD操作
  2. html模块开发模板引擎,一个前端html模板处理引擎(javascript)
  3. 四个变量的图表怎么做_年终总结必备:Excel双色图表怎么做?数据表达更直观...
  4. python装饰器常见问题_关于python装饰器的问题
  5. mysql待办事项表名_SSD8-Ex4待办事项列表答案参考
  6. 【小白学习PyTorch教程】十七、 PyTorch 中 数据集torchvision和torchtext
  7. 深度学习和目标检测系列教程 10-300:通过torch训练第一个Faster-RCNN模型
  8. 四十七、面试前,必须搞懂Java中的线程池ThreadPoolExecutor(上篇)
  9. leetcode 刷题140 141
  10. pytorch 和nltk 结合训练的例子