Android 异步链式调用设计

本文讨论一下异步链式调用的设计与实现。

考虑如下情况:

情况1:

访问网络(或其他耗时的事情)。通常的做法是:

1、显示一个ProgressDialog对话框,提示用户。

2、启动工作线程来执行耗时操作。

3、发送消息到关联到主线程的Handler里面,关闭对话框。

情况2:

 

从网络下载一个zip文件,下载完成之后,询问用户是否执行解压操作。通常的合理做法:

1、显示一个ProgressDialog对话框,提示用户。

2、启动线程执行下载操作。

3、发送消息到关联到主线程的Handler里面,关闭对话框,然后启动一个询问对话框。

4、用户如果点击[YES],显示一个ProgressDialog对话框。

5、启动用线程执行解压操作。

6、发送消息到关联到主线程的Handler里面,关闭对话框。


通常情况下,在Android我们有两种方式来使用线程,一是Thread + Handler这种标准方式,另外一种是使用AsyncTask类。

实现这两个情况的缺点:

 

1、定义Handler,发送消息,使得代码变得复杂,不易理解。

2、发送消息是异步处理,在某些情况下可能需要做等待操作。

3、流程执行混乱,不是流水作业。

基于以上情况,我们能不能也像流水线的操作那么调用我们的回调(Callback),使用者只关心第一步干什么,第二步干什么,如果能这样的话,那么在哪步做什么都能明确定义出来,这就是链式调用。

 

请看下面的链式调用的写法(JavaScript): 

Async.go(initialArgument)

   .next(firstAsyncOperation)

   .next(secondAsyncOperation)

   .next(thirdAsyncOperation)

   .next(function(finalResult) { alert(finalResult); })

 

用户只需要添加每一步的task到一个队列里面,然后执行,这些task就会按添加的顺序执行,从而实现链式调用。

这种思想还不挺好的,在写代码的时候,我们更加关注实现的逻辑,不需要去考虑发什么消息等。只考虑第一步干什么,第二步干什么等。这样在以后代码维护时也比较好。

我们能不能设计出一个Android版本的异步链式调用的模块呢,请看下面。

Task

 

我们抽象出每一步要做的事情,定义一个Task类,它是一个抽象类,有如下核心属性和方法:

mRunInBackground
用来指示这个Task是运行在后台线程还是运行在主线程。

onExecuter(TaskOperation)
我们需要实现该方法,在这里面执行我们想要做的事情。

onProgressUpdate(Object)
我们可以重写该方法,来更新我们所做事情的进度,这个方法运行在主线程。

注意:在使用时,你必须指定这个Task是运行在UI线程还是后台线程。


TaskOperation

 

1)这个类里面包含了task的运行参数,上一个task的输出将会作为下一个task的输入。

2)它可以指示继续或暂停执行下一个task。

3)它里面使用了一个object[]来存储参数。


TaskManager

1)管理task队列,始终从队列第一个开始执行,执行一个task后,这个task将从队列出移除。

2)内部创建了一个带有消息循环的线程。

3)执行task时,判断其运行的线程环境,如果运行在UI线程,发送消息到UI的Handler来执行。

4)内部封装了Handler,用户不用关心是否发送消息。

5)核心方法有:
     - next(Task)
     - execute()
     - execute(TaskOperation)
     - cancelCurrentTask()
     - removeTasks()
     - publishProgress(Object)

这里只是给了一个最基本的设计思路,现在该设计还有完善的地方,具体的实现请参考相关的代码和测试工程。

 

实现代码

Task.java

 

/*

 * System: CoreLib

 * @version     1.00

 * 

 * Copyright (C) 2010, LiHong

 * 

 */



package com.nj1s.lib.task;



import java.util.concurrent.atomic.AtomicBoolean;



/**

 * <p>

 * This method define the task used to do something. Typically you should override

 * {@link #onExecute(TaskOperation)} method to do you things, on the other hand, you 

 * also can override the {@link #onProgressUpdate(Object)} method to get the progress of

 * you things.

 * </p>

 * 

 * <p>

 * NOTE:

 * There is an very important thing you should pay attention to, you must specify the task

 * is running on background thread or UI thread, the default flag is true ---- running on

 * background thread.

 * </p>

 * 

 * @author LeeHong

 * 

 * @date 2012/10/30

 */

public abstract class Task

{

    /**

     * The id of the task, typically you need NOT set it, if will set automatically when you

     * add this task into {@link TaskManager} class.

     */

    private int             mId               = 0;

    

    /**

     * The task name.

     */

    private String          mName             = null;

    

    /**

     * Indicate this task is canceled or not.

     */

    private AtomicBoolean   mCancelled        = new AtomicBoolean(false);

    

    /**

     * The task status, default value is {@link Status#PENDING}.

     */

    private volatile Status mStatus           = Status.PENDING;



    /**

     * The running status, default value is {@link RunningStatus#UI_THREAD}.

     */

    private volatile RunningStatus mRunStatus = RunningStatus.UI_THREAD;

    

    /**

     * Indicates the current status of the task. Each status will be set only once

     * during the lifetime of a task.

     */

    public enum Status 

    {

        /**

         * Indicates that the task has not been executed yet.

         */

        PENDING,

        

        /**

         * Indicates that the task is running.

         */

        RUNNING,

        

        /**

         * Indicates that {@link Task#onExecute} has finished.

         */

        FINISHED,

    }

    

    /**

     * Indicate the task running status.

     */

    public enum RunningStatus

    {

        /**

         * Indicate the task is running in the background thread.

         */

        WORK_THREAD,

        

        /**

         * Indicate the task is running in the UI thread.

         */

        UI_THREAD,

    }

    

    /**

     * The constructor method.

     * 

     * @param runInBackground

     * @param name

     */

    public Task(Task task)

    {

        this.mRunStatus = task.mRunStatus;

        this.mName      = task.mName;

        this.mStatus    = task.mStatus;

    }

    

    /**

     * The constructor method.

     * 

     * @param status indicate the task is running in background thread or not.

     */

    public Task(RunningStatus status)

    {

        this(status, null);

    }

    

    /**

     * The constructor method.

     * 

     * @param runInBackground

     * @param name

     */

    public Task(RunningStatus status, String name)

    {

        mRunStatus = status;

        mName = name;

    }

    

    /**

     * Override this method to do you works.

     * 

     * @param operation The operation is passed from previous task.

     * 

     * @return Typically you should return the {@link #operation}.

     */

    public abstract TaskOperation onExecute(TaskOperation operation);

    

    /**

     * Called when change the progress, this method is running in UI thread.

     * 

     * @param progresses

     */

    public void onProgressUpdate(Object progresses)

    {

    }

    

    /**

     * Cancel the task.

     */

    public void cancel()

    {

        mCancelled.set(true);

    }



    /**

     * Indicate the task is canceled or not.

     * 

     * @return

     */

    public boolean isCancelled()

    {

        return mCancelled.get();

    }

    

    /**

     * Get the running status.

     * 

     * @return

     */

    public RunningStatus getRunningStatus()

    {

        return mRunStatus;

    }



    /**

     * Set the name of the task.

     * 

     * @param name The task name.

     */

    public void setTaskName(String name)

    {

        mName = name;

    }



    /**

     * Get the task name.

     * 

     * @return the task name.

     */

    public String getTaskName()

    {

        return mName;

    }

    

    /**

     * Set the status of the task.

     * 

     * @param status

     */

    public void setStatus(Status status)

    {

        mStatus = status;

    }

    

    /**

     * Get the status of the task.

     * 

     * @return

     */

    public Status getStatus()

    {

        return mStatus;

    }



    /**

     * Set the id of the task.

     * 

     * @param id

     */

    public void setTaskId(int id)

    {

        mId = id;

    }



    /**

     * Get the task id.

     */

    public int getTaskId()

    {

        return mId;

    }

    

    /**

     * @see java.lang.Object#toString()

     */

    @Override

    public String toString()

    {

        StringBuilder sb = new StringBuilder();

        sb.append("name = ").append(mName).append("  ");

        sb.append("id = ").append(mId).append("  ");

        sb.append(super.toString());

        

        return sb.toString();

    }

}

 

 

TaskOperation.java

 

 

/*

 * System: CoreLib

 * @version     1.00

 * 

 * Copyright (C) 2010, LiHong.

 */



package com.nj1s.lib.task;



import java.util.ArrayList;



import com.nj1s.lib.task.TaskManager.TaskManagerState;



/**

 * The task operation, it wraps the task parameter, etc.

 * 

 * @author LeeHong

 *

 * @date 2012/10/30

 */

public class TaskOperation

{

    /**

     * The task parameter.

     */

    private Object[] mNextTaskParams    = null;

    

    /**

     * The task manager status.

     */

    private TaskManagerState mTaskManagerStatus = TaskManagerState.CONTINUE;

    

    /**

     * The constructor method.

     */

    public TaskOperation()

    {

    }

    

    /**

     * The constructor method.

     *  

     * @param nextTaskParams

     */

    public TaskOperation(Object[] nextTaskParams)

    {

        mNextTaskParams  = nextTaskParams;

    }

    

    /**

     * The constructor method.

     * 

     * @param operation

     */

    public TaskOperation(TaskOperation operation)

    {

        setTaskParams(operation);

    }

    

    /**

     * Get the task parameter.

     */

    public Object[] getTaskParams()

    {

        return mNextTaskParams;

    }

    

    /**

     * Set the task parameter.

     * 

     * @param params

     */

    public void setTaskParams(Object[] params)

    {

        mNextTaskParams = params;

    }

    

    /**

     * Set the task parameters.

     * 

     * @param operation

     */

    public void setTaskParams(TaskOperation operation)

    {

        if (operation == this)

        {

            throw new IllegalArgumentException("The argument can NOT be self.");

        }

        

        if (null == operation)

        {

            return;

        }

        

        Object[] params = operation.getTaskParams();

        if (null == params)

        {

            return;

        }

        

        ArrayList<Object> paramsList = new ArrayList<Object>();

        

        if (null != mNextTaskParams)

        {

            for (Object param : mNextTaskParams)

            {

                paramsList.add(param);

            }

        }

        

        for (Object param : params)

        {

            paramsList.add(param);

        }

        

        mNextTaskParams = paramsList.toArray();

    }

    

    /**

     * @param status the mTaskManagerStatus to set

     */

    public void setTaskManagerStatus(TaskManagerState status)

    {

        mTaskManagerStatus = status;

    }



    /**

     * @return the mTaskManagerStatus

     */

    public TaskManagerState getTaskManagerStatus()

    {

        return mTaskManagerStatus;

    }

    

    /**

     * Append the specified parameter to the end of the parameter list.

     * 

     * @param param

     */

    public void appendTaskParam(Object param)

    {

        appendTaskParams(new Object[] {param});

    }

    

    /**

     * Append the specified parameter to the end of the parameter list.

     * 

     * @param params

     */

    public void appendTaskParams(Object[] params)

    {

        if (null != params)

        {

            TaskOperation operation = new TaskOperation(params);

            setTaskParams(operation);

        }

    }

}

 

 

TaskManager.java

 

 

/*

 * System: CoreLib

 * @version     1.00

 * 

 * Copyright (C) 2010, LiHong.

 * 

 */



package com.nj1s.lib.task;



import java.util.HashMap;

import java.util.LinkedList;



import android.os.Handler;

import android.os.Looper;

import android.os.Message;

import android.text.TextUtils;

import android.util.Log;



import com.nj1s.lib.task.Task.RunningStatus;

import com.nj1s.lib.task.Task.Status;

import com.nj1s.lib.thread.ThreadWorker;



/**

 * This class is used to manager the tasks so that you can add many tasks into the task manger

 * and these tasks will be running one by one.

 * 

 * <h2>Example:</h2>

 * <pre class="prettyprint">

 * private void showProgressDialog()

 * {

 *     final ProgressDialog mProgressDialog = null;

 *     final TaskManager taskManager = new TaskManager("ShowProgressDlg");

 *     

 *     // Set the state change listener.

 *     taskManager.setStateChangeListener(new IStateChangeListener()

 *     {

 *         public void onStateChanged(TaskManager taskManager, State oldState, State newState)

 *         {

 *             Toast.makeText(ShowProgressDlgActivity.this, " onStateChanged state = " + newState, Toast.LENGTH_SHORT).show();

 *         }

 *     });

 *     

 *     taskManager

 *     .next(new Task(Task.RunningStatus.UI_THREAD)

 *     {

 *         public TaskOperation onExecute(TaskOperation operation)

 *         {

 *             mProgressDialog = new ProgressDialog(ShowProgressDlgActivity.this);

 *             mProgressDialog.setTitle("Download");

 *             mProgressDialog.setMessage("Downlonding data from server...");

 *             mProgressDialog.setCancelable(false);

 *             mProgressDialog.show();

 *             

 *             return null;

 *         }

 *     })

 *     .next(new Task(Task.RunningStatus.WORK_THREAD)

 *     {

 *         public TaskOperation onExecute(TaskOperation operation)

 *         {

 *             // Simulate the work thread.

 *             sleep(5000);

 *             

 *             return null;

 *         }

 *     })

 *     .next(new Task(Task.RunningStatus.UI_THREAD)

 *     {

 *         public TaskOperation onExecute(TaskOperation operation)

 *         {

 *             if (null != mProgressDialog && mProgressDialog.isShowing())

 *             {

 *                 mProgressDialog.dismiss();

 *                 mProgressDialog = null;

 *             }

 *             

 *             return null;

 *         }

 *     })

 *     .execute();    // Call this method to execute these tasks.

 * }

 * </pre>

 * 

 * <h2>Note:</h2>

 * <pre>

 * The {@link Task} class must be specified the task running state, one of the enum {@link Task#RunningStatus}.

 * </pre>

 * 

 * @author LeeHong

 * 

 * @date 2012/10/30

 * 

 * @see {@link Task}

 * @see {@link TaskOperation}

 */

public class TaskManager

{

    /**

     * Execute task message.

     */

    private static final int MESSAGE_POST_EXECUTE  = 0x01;

    

    /**

     * Update progress message.

     */

    private static final int MESSAGE_POST_PROGRESS = 0x02;

    

    /**

     * The state change listener.

     */

    public interface IStateChangeListener

    {

        /**

         * Called when the task manager's state is changed. This method will be called in

         * UI thread.

         * 

         * @param taskManager Which task manager's state changed.

         * @param oldState The old state.

         * @param newState The new state.

         */

        public void onStateChanged(TaskManager taskManager, State oldState, State newState);

    }

    

    /**

     * A representation of a task manager's state. A given thread may only be in one

     * state at a time.

     */

    public enum State

    {

        /**

         * The task manager has been created, but has never been started.

         */

        NEW,

        

        /**

         * Indicate the task manager is running one task.

         */

        RUNNING,

        

        /**

         * Indicate the task manager is paused, typically call {@link #pause()} method.

         */

        PAUSED,

        

        /**

         * All tasks are finished.

         */

        FINISHED,

    }

    

    /**

     * The status of the {@link TaskManager} class.

     */

    public enum TaskManagerState

    {

        /**

         * Continue the task manager to run next task.

         */

        CONTINUE,

        

        /**

         * Indicate the task manager pause to run next task.

         */

        PAUSE,

    }

    

    /**

     * The running task manager collection.

     */

    private static HashMap<String, TaskManager> s_taskManagers = new HashMap<String, TaskManager>();

    

    /**

     * The task list.

     */

    private LinkedList<Task>    mTaskList       = new LinkedList<Task>();

    

    /**

     * The task operation, it will pass from first task to the last task.

     */

    private TaskOperation       mTaskOperation  = new TaskOperation();

    

    /**

     * The running thread worker, it own a looper which will be alive until you call

     * {@link ThreadWorker#quit()} method.

     */

    private ThreadWorker        mThreadWorker   = null;

    

    /**

     * The current perform task, may be null.

     */

    private Task                mCurTask        = null;

    

    /**

     * The state of the task manager.

     */

    private State               mState          = State.NEW;

    

    /**

     * The name of the task manager.

     */

    private String              mName           = null;

    

    /**

     * The listener.

     */

    private IStateChangeListener mListener      = null;

    

    /**

     * The background thread handler, which is associated to a background thread looper.

     */

    private Handler             mThreadHandler  = null;

    

    /**

     * The UI thread handler.

     */

    private Handler             mUIHandler      = new Handler(Looper.getMainLooper())

    {

        @Override

        public void handleMessage(Message msg)

        {

            switch (msg.what)

            {

            case MESSAGE_POST_EXECUTE:

                Task task = (Task)msg.obj;

                executeTask(task);

                // Try to run next task if possible.

                runNextTask();

                break;

                

            case MESSAGE_POST_PROGRESS:

                postProgress(msg.obj);

                break;

            }

        }

    };

    

    /**

     * The constructor method.

     */

    public TaskManager()

    {

    }

    

    /**

     * The constructor method.

     * 

     * @param name The name of the task manager.

     */

    public TaskManager(String name)

    {

        mName = name;

    }

    

    /**

     * Add the task to {@link TaskManager} class.

     * 

     * @param task The task.

     * 

     * @return the {@link TaskManager} object.

     */

    public TaskManager next(Task task)

    {

        if (null != task)

        {

            synchronized (mTaskList)

            {

                int id = mTaskList.size() + 1;

                task.setTaskId(id);

                mTaskList.add(task);

            }

        }

        else

        {

            throw new NullPointerException("task is null");

        }

        

        return this;

    }

    

    /**

     * Start to execute the tasks in the task manager.

     */

    public void execute()

    {

        if (mTaskList.size() > 0)

        {

            startThread();

            

            // Set the task to RUNNING.

            setState(State.RUNNING);

            

            // Perform the runnable in the handler which is associated to the background thread. 

            mThreadHandler.post(new Runnable()

            {

                @Override

                public void run()

                {

                    doInBackground();

                }

            });

        }

        else

        {

            quitLooper();

        }

    }

    

    /**

     * Start to execute the tasks in the task manager with the specified parameter.

     * 

     * @param operation The task operation contains the task parameter.

     */

    public void execute(TaskOperation operation)

    {

        if (null != operation)

        {

            mTaskOperation = operation;

        }

        

        execute();

    }

    

    /**

     * Post execute a task which will be running in UI thread.

     * 

     * @param task the task to be running.

     */

    public void postExecute(Task task)

    {

        if (null == task)

        {

            throw new NullPointerException("Task can NOT be null.");

        }

        

        final Task runTask = task;

        

        // If the task running status is UI_THREAD.

        if (RunningStatus.UI_THREAD == runTask.getRunningStatus())

        {

            // The task is running in UI thread.

            mUIHandler.post(new Runnable()

            {

                @Override

                public void run()

                {

                    executeTask(runTask);

                }

            });

        }

    }

    

    /**

     * Publish the task progress, if you call this method, the {@link Task#onProgressUpdate(Object)}

     * method will be called, which is running in the UI thread.

     * 

     * @param progresses The progress.

     */

    public void publishProgress(Object progresses)

    {

        mUIHandler.obtainMessage(MESSAGE_POST_PROGRESS, progresses).sendToTarget();

    }

    

    /**

     * Cancel the current running task.

     */

    public void cancelCurrentTask()

    {

        if (null != mCurTask)

        {

            mCurTask.cancel();

        }

    }

    

    /**

     * Remove the tasks in the list.

     */

    public void removeTasks()

    {

        synchronized (mTaskList)

        {

            if (mTaskList.size() > 0)

            {

                mTaskList.clear();

                quitLooper();

            }

        }

    }

    

    /**

     * Remove the specified task.

     * 

     * @param task The task to be removed.

     */

    public void removeTask(Task task)

    {

        synchronized (mTaskList)

        {

            mTaskList.remove(task);

            

            if (mTaskList.isEmpty())

            {

                quitLooper();

            }

        }

    }

    

    /**

     * Set the state change listener.

     * 

     * @param listener

     */

    public void setStateChangeListener(IStateChangeListener listener)

    {

        mListener = listener;

    }

    

    /**

     * Get the task operation.

     * 

     * @return

     */

    public TaskOperation getTaskOperation()

    {

        return mTaskOperation;

    }

    

    /**

     * @return the mName

     */

    public String getName()

    {

        return mName;

    }

    

    /**

     * Pause the worker thread.

     */

    public void pause()

    {

        if (null != mThreadWorker)

        {

            setState(State.PAUSED);

            

            mThreadWorker.pause();

        }

    }

    

    /**

     * Resume the worker thread from the waiting status.

     */

    public void resume()

    {

        if (null != mThreadWorker)

        {

            setState(State.RUNNING);

            

            mThreadWorker.restart();

        }

    }

    

    /**

     * Quit the looper so that the thread can finish correctly.

     */

    public void quitLooper()

    {

        if (null != mThreadWorker)

        {

            mThreadWorker.quit();

            mThreadWorker = null;

        }

        

        mThreadHandler = null;

        

        // Set the task to FINISHED.

        setState(State.FINISHED);

    }

    

    /**

     * Blocks the current thread ({@link Thread#currentThread()}) until the receiver finishes its execution and dies.

     */

    public final void join()

    {

        if (null != mThreadWorker)

        {

            mThreadWorker.join();

        }

    }

    

    /**

     * Get the task manager state.

     * 

     * @return

     */

    public State getState()

    {

        return mState;

    }

    

    /**

     * Get the running task manager.

     * 

     * @return HashMap<String, TaskManager>, the task manager's name is the key, and the

     * task manager object is the value.

     */

    public static HashMap<String, TaskManager> getTaskManagers()

    {

        return s_taskManagers;

    }

    

    /**

     * @see java.lang.Object#toString()

     */

    @Override

    public String toString()

    {

        StringBuilder sb = new StringBuilder();

        sb.append("Name = ").append(mName).append("  ");

        sb.append("State = ").append(mState).append("  ");

        sb.append(super.toString());

        

        return sb.toString();

    }

    

    /**

     * print task execute status

     * 

     * @param task

     */

    protected void printExecuteTaskState(Task task)

    {

        Log.d("TaskManager", "    Executer the task: " + task.toString());

    }

    

    /**

     * Set the state.

     * 

     * @param state

     */

    private void setState(State state)

    {

        final State oldState = mState;

        final State newState = state;

        mState = state;

        

        if (mState == State.FINISHED)

        {

            popTaskManager(this);

        }

        else

        {

            pushTaskManager(this);

        }

        

        if (oldState != newState)

        {

            printTaskManagerState(oldState, newState);

            performStateChange(oldState, newState);

        }

    }

    

    /**

     * Call this method to start the work thread if can.

     */

    private void startThread()

    {

        if (null == mThreadWorker)

        {

            String name = TextUtils.isEmpty(mName) ? this.toString() : mName;

            String threadName = "TaskManager_Thread_" + name;

            mThreadWorker  = new ThreadWorker(threadName);

            mThreadHandler = new Handler(mThreadWorker.getLooper());

        }

    }

    

    /**

     * This method is running in the background thread.

     */

    private void doInBackground()

    {

        mCurTask = null;

        

        if (mTaskList.isEmpty())

        {

            return;

        }

        

        Task task = mTaskList.get(0);

        mCurTask = task;

        

        // Remove the first item in the list.

        synchronized (mTaskList)

        {

            mTaskList.remove(0);

        }



        // If the task is allowed to be running in background thread, we execute the task

        // now, the doInBackground() method is running in the background thread.

        switch (task.getRunningStatus())

        {

        case WORK_THREAD:

            executeTask(task);

            // Try to run next task if possible.

            runNextTask();

            break;

            

        case UI_THREAD:

            // Send a message to the UI handler to executer the task.

            mUIHandler.obtainMessage(MESSAGE_POST_EXECUTE, task).sendToTarget();

            break;

        }

    }



    /**

     * Run the next task.

     */

    private void runNextTask()

    {

        // If run next, call the execute() method again.

        if (isRunNext())

        {

            execute();

        }

    }

    

    /**

     * Check whether run the next task if has one.

     * 

     * @return true if run next task, otherwise false.

     */

    private boolean isRunNext()

    {

        boolean isRunNext = true;

        boolean hasNext   = false;

        

        if (null != mTaskOperation)

        {

            isRunNext = (mTaskOperation.getTaskManagerStatus() == TaskManagerState.CONTINUE);

        }

        

        if (null != mTaskList)

        {

            hasNext = mTaskList.size() > 0;

        }

        

        // No next task, quit the thread.

        if (!hasNext)

        {

            quitLooper();

        }

        

        return (isRunNext && hasNext);

    }

    

    /**

     * Execute the task, if will call {@link Task#onExecute(TaskOperation)} method.

     * 

     * @param task The task object.

     */

    private void executeTask(Task task)

    {

        if (null != task)

        {

           

            

            // Set the status of the task.

            task.setStatus(Status.RUNNING);

            

            // Print the task state.

            this.printExecuteTaskState(task);

            

            try

            {

                // Avoid the exception from task interrupting the task manager works.

                mTaskOperation = task.onExecute(mTaskOperation);

            }

            catch (Exception e)

            {

                e.printStackTrace();

            }

            

            // Set the status of the task.

            task.setStatus(Status.FINISHED);

            

            // Print the task state.

            this.printExecuteTaskState(task);

        }

    }

    

    /**

     * Post the progress, it will call  {@link Task#onProgressUpdate(Object progresses)} method.

     * 

     * @param progresses

     */

    private void postProgress(Object progresses)

    {

        if (null != mCurTask)

        {

            mCurTask.onProgressUpdate(progresses);

        }

    }

    

    /**

     * Perform the state change.

     * 

     * @param oldState

     * @param newState

     */

    private void performStateChange(final State oldState, final State newState)

    {

        if (null != mListener)

        {

            mUIHandler.post(new Runnable()

            {

                @Override

                public void run()

                {

                    mListener.onStateChanged(TaskManager.this, oldState, newState);

                }

            });

        }

    }

    

    /**

     * Print the task manager information.

     * 

     * @param oldState

     * @param newState

     */

    private void printTaskManagerState(final State oldState, final State newState)

    {

        Log.d("TaskManager", "TaskManager state changed, task manager = " + this.toString());

    }

    

    /**

     * Push the task manager to the list.

     * 

     * @param taskManager

     */

    private static void pushTaskManager(TaskManager taskManager)

    {

        if (null != taskManager)

        {

            String name = taskManager.getName();

            if (!TextUtils.isEmpty(name))

            {

                s_taskManagers.put(name, taskManager);

            }

        }

    }

    

    /**

     * Pop the task manager from the list.

     * @param taskManager

     */

    private static void popTaskManager(TaskManager taskManager)

    {

        if (null != taskManager)

        {

            String name = taskManager.getName();

            s_taskManagers.remove(name);

        }

    }

}


 



 

你可能感兴趣的:(android)