转载请标明出处: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. usaco Sorting a Three-Valued Sequence 三值的排序
  2. IIS中保持HTTP连接
  3. input禁止光标_表单中readonly的input等标签,禁止光标进入(focus)的几种方式
  4. 关于 MySQL5.7.log 版本导出 SQL 语句再导入 8.0.13 版本出现 Incorrect datetime value: ‘0000-00-00 00:00:00‘ 错误的解决办法
  5. PHP实用小程序(四)
  6. Arthas 使用的四种方式
  7. c语言lua读文件,file-io – 在Lua中逐行读取文件
  8. SQL Server存储过程初学者
  9. leetcode885.SpiralMatrixIII
  10. Codeforces Round #164 (Div. 2):B. Buttons
  11. Netty的并发编程实践1:正确使用锁
  12. [翻译]XNA外文博客文章精选之sixteen(下)
  13. rabbitmq direct 多个消费者_rabbitMQ消息队列入门介绍
  14. 前端开发者思考:假如5年后你是开发总监
  15. mysql的连接名和用户名_MySQL登陆认证用户名先后顺序
  16. 好看的登陆界面java_简单又美观的登录界面
  17. C#操作Excel表
  18. 南京大学声学基础(第三版)杜功焕第一章
  19. app小程序手机端Python爬虫实战02-uiautomator2自动化抓取开发环境搭建
  20. 北京十一中学,小型数控机床培训,让学生自己设计加工指尖陀铝

热门文章

  1. mysql正则提取字符串_mysql字符串查找截取与正则表达式的联合应用
  2. oracle语句within,oracle中within group的用法
  3. javaweb 解决请求相应的乱码问题
  4. 八十五、再探希尔排序,桶排序,计数排序和基数排序
  5. 五十九、如何求N个数的最大公约数和最小公倍数
  6. EnvironmentError: [WinError 5] 拒绝访问
  7. python 学习 我推荐这本书,适合特别没有程序基础或者编程思维较差的人,
  8. 自动驾驶前沿综述:基于深度强化学习的自动驾驶算法
  9. Perturbed Masking:和参数无关的预训练模型分析方法
  10. 重构世界的真实,6万奖金的超分辨率图像性能挑战赛邀你来战!