Android 异步链式调用设计
本文讨论一下异步链式调用的设计与实现。
考虑如下情况:
情况1:
访问网络(或其他耗时的事情)。通常的做法是:
1、显示一个ProgressDialog对话框,提示用户。
2、启动工作线程来执行耗时操作。
3、发送消息到关联到主线程的Handler里面,关闭对话框。
情况2:
从网络下载一个zip文件,下载完成之后,询问用户是否执行解压操作。通常的合理做法:
1、显示一个ProgressDialog对话框,提示用户。
2、启动线程执行下载操作。
3、发送消息到关联到主线程的Handler里面,关闭对话框,然后启动一个询问对话框。
4、用户如果点击[YES],显示一个ProgressDialog对话框。
5、启动用线程执行解压操作。
6、发送消息到关联到主线程的Handler里面,关闭对话框。
通常情况下,在Android我们有两种方式来使用线程,一是Thread + Handler这种标准方式,另外一种是使用AsyncTask类。
实现这两个情况的缺点:
1、定义Handler,发送消息,使得代码变得复杂,不易理解。
2、发送消息是异步处理,在某些情况下可能需要做等待操作。
3、流程执行混乱,不是流水作业。
基于以上情况,我们能不能也像流水线的操作那么调用我们的回调(Callback),使用者只关心第一步干什么,第二步干什么,如果能这样的话,那么在哪步做什么都能明确定义出来,这就是链式调用。
请看下面的链式调用的写法(JavaScript):
- Async.go(initialArgument)
- .next(firstAsyncOperation)
- .next(secondAsyncOperation)
- .next(thirdAsyncOperation)
- .next(function(finalResult) { alert(finalResult); })
用户只需要添加每一步的task到一个队列里面,然后执行,这些task就会按添加的顺序执行,从而实现链式调用。
这种思想还不挺好的,在写代码的时候,我们更加关注实现的逻辑,不需要去考虑发什么消息等。只考虑第一步干什么,第二步干什么等。这样在以后代码维护时也比较好。
我们能不能设计出一个Android版本的异步链式调用的模块呢,请看下面。
Task
我们抽象出每一步要做的事情,定义一个Task类,它是一个抽象类,有如下核心属性和方法:
mRunInBackground
用来指示这个Task是运行在后台线程还是运行在主线程。
onExecuter(TaskOperation)
我们需要实现该方法,在这里面执行我们想要做的事情。
onProgressUpdate(Object)
我们可以重写该方法,来更新我们所做事情的进度,这个方法运行在主线程。
注意:在使用时,你必须指定这个Task是运行在UI线程还是后台线程。
TaskOperation
1)这个类里面包含了task的运行参数,上一个task的输出将会作为下一个task的输入。
2)它可以指示继续或暂停执行下一个task。
3)它里面使用了一个object[]来存储参数。
TaskManager
1)管理task队列,始终从队列第一个开始执行,执行一个task后,这个task将从队列出移除。
2)内部创建了一个带有消息循环的线程。
3)执行task时,判断其运行的线程环境,如果运行在UI线程,发送消息到UI的Handler来执行。
4)内部封装了Handler,用户不用关心是否发送消息。
5)核心方法有:
- next(Task)
- execute()
- execute(TaskOperation)
- cancelCurrentTask()
- removeTasks()
- publishProgress(Object)
这里只是给了一个最基本的设计思路,现在该设计还有完善的地方,具体的实现请参考相关的代码和测试工程。
实现代码
Task.java
- /*
- * System: CoreLib
- * @version 1.00
- *
- * Copyright (C) 2010, LiHong
- *
- */
- package com.nj1s.lib.task;
- import java.util.concurrent.atomic.AtomicBoolean;
- /**
- * <p>
- * This method define the task used to do something. Typically you should override
- * {@link #onExecute(TaskOperation)} method to do you things, on the other hand, you
- * also can override the {@link #onProgressUpdate(Object)} method to get the progress of
- * you things.
- * </p>
- *
- * <p>
- * NOTE:
- * There is an very important thing you should pay attention to, you must specify the task
- * is running on background thread or UI thread, the default flag is true ---- running on
- * background thread.
- * </p>
- *
- * @author LeeHong
- *
- * @date 2012/10/30
- */
- public abstract class Task
- {
- /**
- * The id of the task, typically you need NOT set it, if will set automatically when you
- * add this task into {@link TaskManager} class.
- */
- private int mId = 0;
- /**
- * The task name.
- */
- private String mName = null;
- /**
- * Indicate this task is canceled or not.
- */
- private AtomicBoolean mCancelled = new AtomicBoolean(false);
- /**
- * The task status, default value is {@link Status#PENDING}.
- */
- private volatile Status mStatus = Status.PENDING;
- /**
- * The running status, default value is {@link RunningStatus#UI_THREAD}.
- */
- private volatile RunningStatus mRunStatus = RunningStatus.UI_THREAD;
- /**
- * Indicates the current status of the task. Each status will be set only once
- * during the lifetime of a task.
- */
- public enum Status
- {
- /**
- * Indicates that the task has not been executed yet.
- */
- PENDING,
- /**
- * Indicates that the task is running.
- */
- RUNNING,
- /**
- * Indicates that {@link Task#onExecute} has finished.
- */
- FINISHED,
- }
- /**
- * Indicate the task running status.
- */
- public enum RunningStatus
- {
- /**
- * Indicate the task is running in the background thread.
- */
- WORK_THREAD,
- /**
- * Indicate the task is running in the UI thread.
- */
- UI_THREAD,
- }
- /**
- * The constructor method.
- *
- * @param runInBackground
- * @param name
- */
- public Task(Task task)
- {
- this.mRunStatus = task.mRunStatus;
- this.mName = task.mName;
- this.mStatus = task.mStatus;
- }
- /**
- * The constructor method.
- *
- * @param status indicate the task is running in background thread or not.
- */
- public Task(RunningStatus status)
- {
- this(status, null);
- }
- /**
- * The constructor method.
- *
- * @param runInBackground
- * @param name
- */
- public Task(RunningStatus status, String name)
- {
- mRunStatus = status;
- mName = name;
- }
- /**
- * Override this method to do you works.
- *
- * @param operation The operation is passed from previous task.
- *
- * @return Typically you should return the {@link #operation}.
- */
- public abstract TaskOperation onExecute(TaskOperation operation);
- /**
- * Called when change the progress, this method is running in UI thread.
- *
- * @param progresses
- */
- public void onProgressUpdate(Object progresses)
- {
- }
- /**
- * Cancel the task.
- */
- public void cancel()
- {
- mCancelled.set(true);
- }
- /**
- * Indicate the task is canceled or not.
- *
- * @return
- */
- public boolean isCancelled()
- {
- return mCancelled.get();
- }
- /**
- * Get the running status.
- *
- * @return
- */
- public RunningStatus getRunningStatus()
- {
- return mRunStatus;
- }
- /**
- * Set the name of the task.
- *
- * @param name The task name.
- */
- public void setTaskName(String name)
- {
- mName = name;
- }
- /**
- * Get the task name.
- *
- * @return the task name.
- */
- public String getTaskName()
- {
- return mName;
- }
- /**
- * Set the status of the task.
- *
- * @param status
- */
- public void setStatus(Status status)
- {
- mStatus = status;
- }
- /**
- * Get the status of the task.
- *
- * @return
- */
- public Status getStatus()
- {
- return mStatus;
- }
- /**
- * Set the id of the task.
- *
- * @param id
- */
- public void setTaskId(int id)
- {
- mId = id;
- }
- /**
- * Get the task id.
- */
- public int getTaskId()
- {
- return mId;
- }
- /**
- * @see java.lang.Object#toString()
- */
- @Override
- public String toString()
- {
- StringBuilder sb = new StringBuilder();
- sb.append("name = ").append(mName).append(" ");
- sb.append("id = ").append(mId).append(" ");
- sb.append(super.toString());
- return sb.toString();
- }
- }
TaskOperation.java
- /*
- * System: CoreLib
- * @version 1.00
- *
- * Copyright (C) 2010, LiHong.
- */
- package com.nj1s.lib.task;
- import java.util.ArrayList;
- import com.nj1s.lib.task.TaskManager.TaskManagerState;
- /**
- * The task operation, it wraps the task parameter, etc.
- *
- * @author LeeHong
- *
- * @date 2012/10/30
- */
- public class TaskOperation
- {
- /**
- * The task parameter.
- */
- private Object[] mNextTaskParams = null;
- /**
- * The task manager status.
- */
- private TaskManagerState mTaskManagerStatus = TaskManagerState.CONTINUE;
- /**
- * The constructor method.
- */
- public TaskOperation()
- {
- }
- /**
- * The constructor method.
- *
- * @param nextTaskParams
- */
- public TaskOperation(Object[] nextTaskParams)
- {
- mNextTaskParams = nextTaskParams;
- }
- /**
- * The constructor method.
- *
- * @param operation
- */
- public TaskOperation(TaskOperation operation)
- {
- setTaskParams(operation);
- }
- /**
- * Get the task parameter.
- */
- public Object[] getTaskParams()
- {
- return mNextTaskParams;
- }
- /**
- * Set the task parameter.
- *
- * @param params
- */
- public void setTaskParams(Object[] params)
- {
- mNextTaskParams = params;
- }
- /**
- * Set the task parameters.
- *
- * @param operation
- */
- public void setTaskParams(TaskOperation operation)
- {
- if (operation == this)
- {
- throw new IllegalArgumentException("The argument can NOT be self.");
- }
- if (null == operation)
- {
- return;
- }
- Object[] params = operation.getTaskParams();
- if (null == params)
- {
- return;
- }
- ArrayList<Object> paramsList = new ArrayList<Object>();
- if (null != mNextTaskParams)
- {
- for (Object param : mNextTaskParams)
- {
- paramsList.add(param);
- }
- }
- for (Object param : params)
- {
- paramsList.add(param);
- }
- mNextTaskParams = paramsList.toArray();
- }
- /**
- * @param status the mTaskManagerStatus to set
- */
- public void setTaskManagerStatus(TaskManagerState status)
- {
- mTaskManagerStatus = status;
- }
- /**
- * @return the mTaskManagerStatus
- */
- public TaskManagerState getTaskManagerStatus()
- {
- return mTaskManagerStatus;
- }
- /**
- * Append the specified parameter to the end of the parameter list.
- *
- * @param param
- */
- public void appendTaskParam(Object param)
- {
- appendTaskParams(new Object[] {param});
- }
- /**
- * Append the specified parameter to the end of the parameter list.
- *
- * @param params
- */
- public void appendTaskParams(Object[] params)
- {
- if (null != params)
- {
- TaskOperation operation = new TaskOperation(params);
- setTaskParams(operation);
- }
- }
- }
TaskManager.java
- /*
- * System: CoreLib
- * @version 1.00
- *
- * Copyright (C) 2010, LiHong.
- *
- */
- package com.nj1s.lib.task;
- import java.util.HashMap;
- import java.util.LinkedList;
- import android.os.Handler;
- import android.os.Looper;
- import android.os.Message;
- import android.text.TextUtils;
- import android.util.Log;
- import com.nj1s.lib.task.Task.RunningStatus;
- import com.nj1s.lib.task.Task.Status;
- import com.nj1s.lib.thread.ThreadWorker;
- /**
- * This class is used to manager the tasks so that you can add many tasks into the task manger
- * and these tasks will be running one by one.
- *
- * <h2>Example:</h2>
- * <pre class="prettyprint">
- * private void showProgressDialog()
- * {
- * final ProgressDialog mProgressDialog = null;
- * final TaskManager taskManager = new TaskManager("ShowProgressDlg");
- *
- * // Set the state change listener.
- * taskManager.setStateChangeListener(new IStateChangeListener()
- * {
- * public void onStateChanged(TaskManager taskManager, State oldState, State newState)
- * {
- * Toast.makeText(ShowProgressDlgActivity.this, " onStateChanged state = " + newState, Toast.LENGTH_SHORT).show();
- * }
- * });
- *
- * taskManager
- * .next(new Task(Task.RunningStatus.UI_THREAD)
- * {
- * public TaskOperation onExecute(TaskOperation operation)
- * {
- * mProgressDialog = new ProgressDialog(ShowProgressDlgActivity.this);
- * mProgressDialog.setTitle("Download");
- * mProgressDialog.setMessage("Downlonding data from server...");
- * mProgressDialog.setCancelable(false);
- * mProgressDialog.show();
- *
- * return null;
- * }
- * })
- * .next(new Task(Task.RunningStatus.WORK_THREAD)
- * {
- * public TaskOperation onExecute(TaskOperation operation)
- * {
- * // Simulate the work thread.
- * sleep(5000);
- *
- * return null;
- * }
- * })
- * .next(new Task(Task.RunningStatus.UI_THREAD)
- * {
- * public TaskOperation onExecute(TaskOperation operation)
- * {
- * if (null != mProgressDialog && mProgressDialog.isShowing())
- * {
- * mProgressDialog.dismiss();
- * mProgressDialog = null;
- * }
- *
- * return null;
- * }
- * })
- * .execute(); // Call this method to execute these tasks.
- * }
- * </pre>
- *
- * <h2>Note:</h2>
- * <pre>
- * The {@link Task} class must be specified the task running state, one of the enum {@link Task#RunningStatus}.
- * </pre>
- *
- * @author LeeHong
- *
- * @date 2012/10/30
- *
- * @see {@link Task}
- * @see {@link TaskOperation}
- */
- public class TaskManager
- {
- /**
- * Execute task message.
- */
- private static final int MESSAGE_POST_EXECUTE = 0x01;
- /**
- * Update progress message.
- */
- private static final int MESSAGE_POST_PROGRESS = 0x02;
- /**
- * The state change listener.
- */
- public interface IStateChangeListener
- {
- /**
- * Called when the task manager's state is changed. This method will be called in
- * UI thread.
- *
- * @param taskManager Which task manager's state changed.
- * @param oldState The old state.
- * @param newState The new state.
- */
- public void onStateChanged(TaskManager taskManager, State oldState, State newState);
- }
- /**
- * A representation of a task manager's state. A given thread may only be in one
- * state at a time.
- */
- public enum State
- {
- /**
- * The task manager has been created, but has never been started.
- */
- NEW,
- /**
- * Indicate the task manager is running one task.
- */
- RUNNING,
- /**
- * Indicate the task manager is paused, typically call {@link #pause()} method.
- */
- PAUSED,
- /**
- * All tasks are finished.
- */
- FINISHED,
- }
- /**
- * The status of the {@link TaskManager} class.
- */
- public enum TaskManagerState
- {
- /**
- * Continue the task manager to run next task.
- */
- CONTINUE,
- /**
- * Indicate the task manager pause to run next task.
- */
- PAUSE,
- }
- /**
- * The running task manager collection.
- */
- private static HashMap<String, TaskManager> s_taskManagers = new HashMap<String, TaskManager>();
- /**
- * The task list.
- */
- private LinkedList<Task> mTaskList = new LinkedList<Task>();
- /**
- * The task operation, it will pass from first task to the last task.
- */
- private TaskOperation mTaskOperation = new TaskOperation();
- /**
- * The running thread worker, it own a looper which will be alive until you call
- * {@link ThreadWorker#quit()} method.
- */
- private ThreadWorker mThreadWorker = null;
- /**
- * The current perform task, may be null.
- */
- private Task mCurTask = null;
- /**
- * The state of the task manager.
- */
- private State mState = State.NEW;
- /**
- * The name of the task manager.
- */
- private String mName = null;
- /**
- * The listener.
- */
- private IStateChangeListener mListener = null;
- /**
- * The background thread handler, which is associated to a background thread looper.
- */
- private Handler mThreadHandler = null;
- /**
- * The UI thread handler.
- */
- private Handler mUIHandler = new Handler(Looper.getMainLooper())
- {
- @Override
- public void handleMessage(Message msg)
- {
- switch (msg.what)
- {
- case MESSAGE_POST_EXECUTE:
- Task task = (Task)msg.obj;
- executeTask(task);
- // Try to run next task if possible.
- runNextTask();
- break;
- case MESSAGE_POST_PROGRESS:
- postProgress(msg.obj);
- break;
- }
- }
- };
- /**
- * The constructor method.
- */
- public TaskManager()
- {
- }
- /**
- * The constructor method.
- *
- * @param name The name of the task manager.
- */
- public TaskManager(String name)
- {
- mName = name;
- }
- /**
- * Add the task to {@link TaskManager} class.
- *
- * @param task The task.
- *
- * @return the {@link TaskManager} object.
- */
- public TaskManager next(Task task)
- {
- if (null != task)
- {
- synchronized (mTaskList)
- {
- int id = mTaskList.size() + 1;
- task.setTaskId(id);
- mTaskList.add(task);
- }
- }
- else
- {
- throw new NullPointerException("task is null");
- }
- return this;
- }
- /**
- * Start to execute the tasks in the task manager.
- */
- public void execute()
- {
- if (mTaskList.size() > 0)
- {
- startThread();
- // Set the task to RUNNING.
- setState(State.RUNNING);
- // Perform the runnable in the handler which is associated to the background thread.
- mThreadHandler.post(new Runnable()
- {
- @Override
- public void run()
- {
- doInBackground();
- }
- });
- }
- else
- {
- quitLooper();
- }
- }
- /**
- * Start to execute the tasks in the task manager with the specified parameter.
- *
- * @param operation The task operation contains the task parameter.
- */
- public void execute(TaskOperation operation)
- {
- if (null != operation)
- {
- mTaskOperation = operation;
- }
- execute();
- }
- /**
- * Post execute a task which will be running in UI thread.
- *
- * @param task the task to be running.
- */
- public void postExecute(Task task)
- {
- if (null == task)
- {
- throw new NullPointerException("Task can NOT be null.");
- }
- final Task runTask = task;
- // If the task running status is UI_THREAD.
- if (RunningStatus.UI_THREAD == runTask.getRunningStatus())
- {
- // The task is running in UI thread.
- mUIHandler.post(new Runnable()
- {
- @Override
- public void run()
- {
- executeTask(runTask);
- }
- });
- }
- }
- /**
- * Publish the task progress, if you call this method, the {@link Task#onProgressUpdate(Object)}
- * method will be called, which is running in the UI thread.
- *
- * @param progresses The progress.
- */
- public void publishProgress(Object progresses)
- {
- mUIHandler.obtainMessage(MESSAGE_POST_PROGRESS, progresses).sendToTarget();
- }
- /**
- * Cancel the current running task.
- */
- public void cancelCurrentTask()
- {
- if (null != mCurTask)
- {
- mCurTask.cancel();
- }
- }
- /**
- * Remove the tasks in the list.
- */
- public void removeTasks()
- {
- synchronized (mTaskList)
- {
- if (mTaskList.size() > 0)
- {
- mTaskList.clear();
- quitLooper();
- }
- }
- }
- /**
- * Remove the specified task.
- *
- * @param task The task to be removed.
- */
- public void removeTask(Task task)
- {
- synchronized (mTaskList)
- {
- mTaskList.remove(task);
- if (mTaskList.isEmpty())
- {
- quitLooper();
- }
- }
- }
- /**
- * Set the state change listener.
- *
- * @param listener
- */
- public void setStateChangeListener(IStateChangeListener listener)
- {
- mListener = listener;
- }
- /**
- * Get the task operation.
- *
- * @return
- */
- public TaskOperation getTaskOperation()
- {
- return mTaskOperation;
- }
- /**
- * @return the mName
- */
- public String getName()
- {
- return mName;
- }
- /**
- * Pause the worker thread.
- */
- public void pause()
- {
- if (null != mThreadWorker)
- {
- setState(State.PAUSED);
- mThreadWorker.pause();
- }
- }
- /**
- * Resume the worker thread from the waiting status.
- */
- public void resume()
- {
- if (null != mThreadWorker)
- {
- setState(State.RUNNING);
- mThreadWorker.restart();
- }
- }
- /**
- * Quit the looper so that the thread can finish correctly.
- */
- public void quitLooper()
- {
- if (null != mThreadWorker)
- {
- mThreadWorker.quit();
- mThreadWorker = null;
- }
- mThreadHandler = null;
- // Set the task to FINISHED.
- setState(State.FINISHED);
- }
- /**
- * Blocks the current thread ({@link Thread#currentThread()}) until the receiver finishes its execution and dies.
- */
- public final void join()
- {
- if (null != mThreadWorker)
- {
- mThreadWorker.join();
- }
- }
- /**
- * Get the task manager state.
- *
- * @return
- */
- public State getState()
- {
- return mState;
- }
- /**
- * Get the running task manager.
- *
- * @return HashMap<String, TaskManager>, the task manager's name is the key, and the
- * task manager object is the value.
- */
- public static HashMap<String, TaskManager> getTaskManagers()
- {
- return s_taskManagers;
- }
- /**
- * @see java.lang.Object#toString()
- */
- @Override
- public String toString()
- {
- StringBuilder sb = new StringBuilder();
- sb.append("Name = ").append(mName).append(" ");
- sb.append("State = ").append(mState).append(" ");
- sb.append(super.toString());
- return sb.toString();
- }
- /**
- * print task execute status
- *
- * @param task
- */
- protected void printExecuteTaskState(Task task)
- {
- Log.d("TaskManager", " Executer the task: " + task.toString());
- }
- /**
- * Set the state.
- *
- * @param state
- */
- private void setState(State state)
- {
- final State oldState = mState;
- final State newState = state;
- mState = state;
- if (mState == State.FINISHED)
- {
- popTaskManager(this);
- }
- else
- {
- pushTaskManager(this);
- }
- if (oldState != newState)
- {
- printTaskManagerState(oldState, newState);
- performStateChange(oldState, newState);
- }
- }
- /**
- * Call this method to start the work thread if can.
- */
- private void startThread()
- {
- if (null == mThreadWorker)
- {
- String name = TextUtils.isEmpty(mName) ? this.toString() : mName;
- String threadName = "TaskManager_Thread_" + name;
- mThreadWorker = new ThreadWorker(threadName);
- mThreadHandler = new Handler(mThreadWorker.getLooper());
- }
- }
- /**
- * This method is running in the background thread.
- */
- private void doInBackground()
- {
- mCurTask = null;
- if (mTaskList.isEmpty())
- {
- return;
- }
- Task task = mTaskList.get(0);
- mCurTask = task;
- // Remove the first item in the list.
- synchronized (mTaskList)
- {
- mTaskList.remove(0);
- }
- // If the task is allowed to be running in background thread, we execute the task
- // now, the doInBackground() method is running in the background thread.
- switch (task.getRunningStatus())
- {
- case WORK_THREAD:
- executeTask(task);
- // Try to run next task if possible.
- runNextTask();
- break;
- case UI_THREAD:
- // Send a message to the UI handler to executer the task.
- mUIHandler.obtainMessage(MESSAGE_POST_EXECUTE, task).sendToTarget();
- break;
- }
- }
- /**
- * Run the next task.
- */
- private void runNextTask()
- {
- // If run next, call the execute() method again.
- if (isRunNext())
- {
- execute();
- }
- }
- /**
- * Check whether run the next task if has one.
- *
- * @return true if run next task, otherwise false.
- */
- private boolean isRunNext()
- {
- boolean isRunNext = true;
- boolean hasNext = false;
- if (null != mTaskOperation)
- {
- isRunNext = (mTaskOperation.getTaskManagerStatus() == TaskManagerState.CONTINUE);
- }
- if (null != mTaskList)
- {
- hasNext = mTaskList.size() > 0;
- }
- // No next task, quit the thread.
- if (!hasNext)
- {
- quitLooper();
- }
- return (isRunNext && hasNext);
- }
- /**
- * Execute the task, if will call {@link Task#onExecute(TaskOperation)} method.
- *
- * @param task The task object.
- */
- private void executeTask(Task task)
- {
- if (null != task)
- {
- // Set the status of the task.
- task.setStatus(Status.RUNNING);
- // Print the task state.
- this.printExecuteTaskState(task);
- try
- {
- // Avoid the exception from task interrupting the task manager works.
- mTaskOperation = task.onExecute(mTaskOperation);
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
- // Set the status of the task.
- task.setStatus(Status.FINISHED);
- // Print the task state.
- this.printExecuteTaskState(task);
- }
- }
- /**
- * Post the progress, it will call {@link Task#onProgressUpdate(Object progresses)} method.
- *
- * @param progresses
- */
- private void postProgress(Object progresses)
- {
- if (null != mCurTask)
- {
- mCurTask.onProgressUpdate(progresses);
- }
- }
- /**
- * Perform the state change.
- *
- * @param oldState
- * @param newState
- */
- private void performStateChange(final State oldState, final State newState)
- {
- if (null != mListener)
- {
- mUIHandler.post(new Runnable()
- {
- @Override
- public void run()
- {
- mListener.onStateChanged(TaskManager.this, oldState, newState);
- }
- });
- }
- }
- /**
- * Print the task manager information.
- *
- * @param oldState
- * @param newState
- */
- private void printTaskManagerState(final State oldState, final State newState)
- {
- Log.d("TaskManager", "TaskManager state changed, task manager = " + this.toString());
- }
- /**
- * Push the task manager to the list.
- *
- * @param taskManager
- */
- private static void pushTaskManager(TaskManager taskManager)
- {
- if (null != taskManager)
- {
- String name = taskManager.getName();
- if (!TextUtils.isEmpty(name))
- {
- s_taskManagers.put(name, taskManager);
- }
- }
- }
- /**
- * Pop the task manager from the list.
- * @param taskManager
- */
- private static void popTaskManager(TaskManager taskManager)
- {
- if (null != taskManager)
- {
- String name = taskManager.getName();
- s_taskManagers.remove(name);
- }
- }
- }
Android 异步链式调用设计的更多相关文章
- 使用Promise链式调用解决多个异步回调的问题
使用Promise链式调用解决多个异步回调的问题 比如我们平常经常遇到的一种情况: 网站中需要先获取用户名,然后再根据用户名去获取用户信息.这里获取用户名getUserName()和获取用户信息get ...
- Android总结之链式调用(方法链)
前言: 最近在学习总结Android属性动画的时候,发现Android的属性动画设计采用了链式调用的方式,然后又回顾了一下了以前接触的开源框架Glide也是采用链式调用的方式,还有最近火的一塌糊涂的R ...
- 如何写 JS 的链式调用 ---》JS 设计模式《----方法的链式调用
1.以$ 函数为例.通常返回一个HTML元素或一个元素集合. 代码如下: function $(){ var elements = []; ;i<arguments.length;i++){ v ...
- Android异步回调中的UI同步性问题
Android程序编码过程中,回调无处不在.从最常见的Activity生命周期回调开始,到BroadcastReceiver.Service以及Sqlite等.Activity.BroadcastRe ...
- 【转】Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38377229 ,本文出自[张鸿洋的博客] 很多人面试肯定都被问到过,请问Andr ...
- Java基础知识强化之网络编程笔记15:Android网络通信之 Android异步任务处理(AsyncTask使用)
AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的 ...
- Android 异步消息处理机制 让你在深入了解 Looper、Handler、Message之间的关系
转载请注明出处:http://blog.csdn.net/lmj623565791/article/details/38377229 ,本文出自[张鸿洋的博客] 非常多人面试肯定都被问到过,请问And ...
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
转自:http://blog.csdn.net/lmj623565791/article/details/38377229 ,本文出自[张鸿洋的博客] 很多人面试肯定都被问到过,请问Android中的 ...
- Android异步处理之AsyncTaskLoader简单使用
简介 不管是在Android应用开发还是Android平台开发中,异步处理通常是最基本的coding要求.如果你还在主线程中写一些数据库,网络请求,读写本地文件等操作的话那说明你还不是一个合格的And ...
随机推荐
- 通过DWR简化AJAX开发
DWR(Direct Web Remoting)是一个WEB远程调用框架,采取了一个类似AJAX的新方法来动态生成基于JAVA类的JavaScript代码.这样WEB开发人员就可以在JavaScrip ...
- [poj 1265]Area[Pick定理][三角剖分]
题意: 给出机器人移动的向量, 计算包围区域的内部整点, 边上整点, 面积. 思路: 面积是用三角剖分, 边上整点与GCD有关, 内部整点套用Pick定理. S = I + E / 2 - 1 I 为 ...
- tcp/ip协议listen函数中backlog參数的含义
listen函数的定义例如以下所看到的: #include <sys/socket.h> int accept(int sockfd, struct sockaddr * restrict ...
- IOS系统对fixed定位支持不好的解决方法
问题: IOS 中所有浏览器,当页面上的输入框获得焦点时,呼出键盘. 页面底部的导航栏(position:fixed)会被键盘顶到页面的中间. 而当输入框失去焦点时,导航栏停留在页面中间,造成页面错乱 ...
- Android屏幕大小适配问题解决
转载: 一.一些基本概念 1.长度(真实长度):英寸.inch 2.分辨率:density 每英寸像素数 dpi(密度) 3.像素:px 4.dip的公式:px /dip=dpi/160 所以 d ...
- PHP - 遍历文件夹下的所有文件名
/** * * 函数名:myreaddir($dir) * 作用:读取目录所有的文件名 * 参数:$dir 目录地址 * 返回值:文件名数组 * * */ function myreaddir($di ...
- MFC 只启动一个程序实例
问题描述: 我们开发过程中可能会经常遇到,只启动一个程序实例.即一个程序启动之后,如果再次执行该程序,将会恢复之前打开的程序,而不是打开一个新的程序. 实现原理:利用FindWindow/FindWi ...
- transition与animation
以前,一直都知道,transition是animation的一个简化版,甚至不算是动画,而是一种过渡. transition的用法 早两天用transition写了一个按钮滑动的效果,类似于IOS的设 ...
- HDU1686——Oulipo
Problem Description The French author Georges Perec (1936–1982) once wrote a book, La disparition, w ...
- DOM querySelector选择器
原生的强大DOM选择器querySelector 在传统的 JavaScript 开发中,查找 DOM 往往是开发人员遇到的第一个头疼的问题,原生的 JavaScript 所提供的 DOM 选择方法并 ...