zoukankan      html  css  js  c++  java
  • Android 从零开始打造异步处理框架

    转载请标明出处: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<T> 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<T> 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<String>(){
    
            @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 <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(){
        }
    
        @Override
        public void run() {
            super.run();
            Message message = Message.obtain() ;
            message.obj = new ResultData<T>( 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 <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() {
                @Override
                public 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() {
                @Override
                public void run() {
                    Message message = Message.obtain() ;
                    message.obj = new ResultData<T>( 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 <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>(){
    
                @Override
                public String onDoInBackground() {
                    return "我是线程";
                }
            }.execute();
    
    • 方式2
        new MyTask().execute();
        
        class MyTask extends ThreadTask<String> {
    
            @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】Android AsyncTask 深度理解、简单封装、任务队列分析、自定义线程池
    【2】Android 自定义线程池的实战
    【3】Java 单例模式
    【4】Android Handler、Loop 的简单使用
    【5】Android 更新UI的几种方式

  • 相关阅读:
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    微信小程序TodoList
    C语言88案例-找出数列中的最大值和最小值
    C语言88案例-使用指针的指针输出字符串
  • 原文地址:https://www.cnblogs.com/zhaoyanjun/p/5995752.html
Copyright © 2011-2022 走看看