Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 異步處理框架

Android 異步處理框架

編輯:關於Android編程

概述

在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. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved