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




  • 5
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 14
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值