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




  • 相关阅读:
    java poi 从服务器下载模板写入数据再导出
    一个华为面试题
    ForEach 循环
    fmt标签格式化数字和时间
    Ichars制作数据统计图
    jQuery中的事件
    oracle学习第四天
    GET请求和POST请求
    Jsp的九个隐含对象
    Oracle学习【语句查询】
  • 原文地址:https://www.cnblogs.com/snake-hand/p/3144852.html
Copyright © 2020-2023  润新知