Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 異步鏈式調用設計

Android 異步鏈式調用設計

編輯:關於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):


[java]
Async.go(initialArgument) 
   .next(firstAsyncOperation) 
   .next(secondAsyncOperation) 
   .next(thirdAsyncOperation) 
   .next(function(finalResult) { alert(finalResult); }) 

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

[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(); 
    } 

/*
 * 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


[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); 
        } 
    } 

/*
 * 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


[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); 
        } 
    } 

/*
 * 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);
        }
    }
}


 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved