package com.glview.hwui.task;
import android.util.Log;
import com.glview.thread.Handler;
import com.glview.thread.Looper;
/**
* A task handler that can run sync tasks.
* @author lijing.lj
*/
public class TaskHandler extends Handler {
final static String TAG = "TaskHandler";
final static boolean DEBUG = false;
public TaskHandler(Looper looper) {
super(looper);
}
public boolean isCurrentThread() {
return getLooper().getThread() == Thread.currentThread();
}
public boolean post(Task task) {
if (DEBUG) Log.d(TAG, "Post a task. task=" + task);
return super.post(task);
}
public boolean postAtFrontOfQueue(Task task) {
if (DEBUG) Log.d(TAG, "Post a task at front of queue. task=" + task);
return super.postAtFrontOfQueue(task);
}
public void remove(Task task) {
super.removeCallbacks(task);
}
/**
* Runs the specified task synchronously.
* <p>
* If the current thread is the same as the handler thread, then the runnable
* runs immediately without being enqueued. Otherwise, posts the runnable
* to the handler and waits for it to complete before returning.
* </p><p>
* This method is dangerous! Improper use can result in deadlocks.
* Never call this method while any locks are held or use it in a
* possibly re-entrant manner.
* </p><p>
* This method is occasionally useful in situations where a background thread
* must synchronously await completion of a task that must run on the
* handler's thread. However, this problem is often a symptom of bad design.
* Consider improving the design (if possible) before resorting to this method.
* </p><p>
* One example of where you might want to use this method is when you just
* set up a Handler thread and need to perform some initialization steps on
* it before continuing execution.
* </p><p>
* If timeout occurs then this method returns <code>false</code> but the runnable
* will remain posted on the handler and may already be in progress or
* complete at a later time.
* </p><p>
* When using this method, be sure to use {@link Looper#quitSafely} when
* quitting the looper. Otherwise {@link #runWithScissors} may hang indefinitely.
* (TODO: We should fix this by making MessageQueue aware of blocking runnables.)
* </p>
*
* @param task The Runnable that will be executed synchronously.
*
*/
public boolean postAndWait(Task task) {
if (DEBUG) Log.d(TAG, "Post a sync task. task=" + task);
if (isCurrentThread()) {
task.run();
return true;
} else {
BlockingRunable blockingRunable = BlockingRunable.obtain(task);
boolean r = blockingRunable.postAndWait(this, -1);
blockingRunable.recycle();
return r;
}
}
public boolean postAtFrontOfQueueAndWait (Task task) {
if (DEBUG) Log.d(TAG, "Post a sync task at front of queue. task=" + task);
if (isCurrentThread()) {
task.run();
return true;
} else {
BlockingRunable blockingRunable = BlockingRunable.obtain(task);
boolean r = blockingRunable.postAtFrontOfQueueAndWait(this, -1);
blockingRunable.recycle();
return r;
}
}
}