博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android 从零开始打造异步处理框架
阅读量:6218 次
发布时间:2019-06-21

本文共 10830 字,大约阅读时间需要 36 分钟。

转载请标明出处:http://www.cnblogs.com/zhaoyanjun/p/5995752.html

本文出自

概述

在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 {    @Override    public 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
extends Thread { @Override public void run() { super.run(); } /** * 任务开始之前调用,运行在主线程 */ @MainThread public void onStart(){ } /** * 子线程中调用,运行在子线程 * @return */ @WorkerThread public abstract T onDoInBackground() ; /** * 子线程返回的结果,运行在主线程 * @param t */ @MainThread public void onResult( T t ){ }}

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

private Handler handler ;    public ThreadTask(){        handler = new Handler( Looper.getMainLooper()){            @Override            public 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
extends Thread { private Handler handler ; public ThreadTask(){ handler = new Handler( Looper.getMainLooper()){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); //在这里接收子线程发过来的消息 onResult((T) msg.obj); } } ; } @Override public void run() { super.run(); Message message = Message.obtain() ; message.obj = onDoInBackground() ; handler.sendMessage( message ) ; } /** * 任务开始之前调用,运行在主线程 */ @MainThread public void onStart(){ } /** * 子线程中调用,运行在子线程 * @return */ @WorkerThread public abstract T onDoInBackground() ; /** * 子线程返回的结果,运行在主线程 * @param t */ @MainThread public void onResult( T t ){ } /** * 开始执行 */ public void execute(){ onStart(); start(); }}

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

new ThreadTask
(){ @Override public void onStart() { super.onStart(); Log.d( "ThreadTask " , "onStart线程:" + Thread.currentThread().getName() ) ; } @Override public String onDoInBackground() { Log.d( "ThreadTask " , "onDoInBackground线程: " + Thread.currentThread().getName() ) ; //模拟耗时操作 try { Thread.sleep( 3000 ); } catch (InterruptedException e) { e.printStackTrace(); } return "结果返回了"; } @Override public 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 );        }        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            //在这里接收子线程发过来的消息            ResultData resultData = (ResultData) msg.obj;            resultData.threadTask.onResult( resultData.data );        }    }
  • ResultData是一个消息实体
/**     * handler发送数据的实体     * @param      */    private static class ResultData{        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
extends Thread { private static Handler handler ; public ThreadTask(){ } @Override public void run() { super.run(); Message message = Message.obtain() ; message.obj = new ResultData
( this , onDoInBackground() ) ; getHandler().sendMessage( message ) ; } /** * 任务开始之前调用,运行在主线程 */ @MainThread public void onStart(){ } /** * 子线程中调用,运行在子线程 * @return */ @WorkerThread public abstract T onDoInBackground() ; /** * 子线程返回的结果,运行在主线程 * @param t */ @MainThread public 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 ); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); //在这里接收子线程发过来的消息 ResultData resultData = (ResultData) msg.obj; resultData.threadTask.onResult( resultData.data ); } } /** * handler发送数据的实体 * @param
*/ private static class ResultData{ 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() {            @Override            public void run() {                Message message = Message.obtain() ;                message.obj = new ResultData
( 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
{ private static Handler handler ; /** * 线程池,创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。 */ private static ExecutorService executorService = Executors.newFixedThreadPool( 15 ) ; public ThreadTask(){ } private void run() { executorService.execute(new Runnable() { @Override public void run() { Message message = Message.obtain() ; message.obj = new ResultData
( ThreadTask.this , onDoInBackground() ) ; getHandler().sendMessage( message ) ; } }); } /** * 任务开始之前调用,运行在主线程 */ @MainThread public void onStart(){ } /** * 子线程中调用,运行在子线程 * @return */ @WorkerThread public abstract T onDoInBackground() ; /** * 子线程返回的结果,运行在主线程 * @param t */ @MainThread public 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 ); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); //在这里接收子线程发过来的消息 ResultData resultData = (ResultData) msg.obj; resultData.threadTask.onResult( resultData.data ); } } /** * handler发送数据的实体 * @param
*/ private static class ResultData{ ThreadTask threadTask ; Data data ; public ResultData( ThreadTask threadTask ,Data data ){ this.threadTask = threadTask ; this.data = data ; } }}

框架使用

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

参考资料

【1】

【2】
【3】
【4】
【5】

你可能感兴趣的文章
SQL CLR学习
查看>>
String的高级用法(String.Format)
查看>>
切,切,切,将文本文件按行分割
查看>>
【翻译】Tomcat 6.0 部署与发布
查看>>
hash_map map
查看>>
自动补全多标签输入, 适合新闻标签/商品标签
查看>>
逻辑操作符、位操作符号的忽略点
查看>>
Explicit keyword
查看>>
后台action处理数据传递给前台界面
查看>>
extJS4.2.0 Json数据解析,嵌套及非嵌套(二)
查看>>
ctrl+c,ctrl+d,ctrl+z在linux中意义
查看>>
安卓开发环境配置及HelloWorld
查看>>
Oracle SQL Developer如何配置TNS
查看>>
KVM 介绍(2):CPU 和内存虚拟化
查看>>
Eclipse 4.4.2 取消空格键代码上屏
查看>>
【Unity3D】自动寻路(Nav Mesh Agent组件)
查看>>
winform视频教程-任务定时循环执行小工具
查看>>
scrapy爬虫成长日记之创建工程-抽取数据-保存为json格式的数据
查看>>
Light OJ 1341 Aladdin and the Flying Carpet Pollard_rho整数分解+DFS
查看>>
BusHelper
查看>>