1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.launcher2; 18 19 import android.os.Handler; 20 import android.os.Looper; 21 import android.os.Message; 22 import android.os.MessageQueue; 23 import android.util.Pair; 24 import java.util.LinkedList; 25 import java.util.ListIterator; 26 27 /** 28 * Queue of things to run on a looper thread. Items posted with {@link #post} will not 29 * be actually enqued on the handler until after the last one has run, to keep from 30 * starving the thread. 31 * 32 * This class is fifo. 33 */ 34 public class DeferredHandler { 35 private LinkedList<Pair<Runnable, Integer>> mQueue = new LinkedList<Pair<Runnable, Integer>>(); 36 private MessageQueue mMessageQueue = Looper.myQueue(); 37 private Impl mHandler = new Impl(); 38 39 private class Impl extends Handler implements MessageQueue.IdleHandler { handleMessage(Message msg)40 public void handleMessage(Message msg) { 41 Pair<Runnable, Integer> p; 42 Runnable r; 43 synchronized (mQueue) { 44 if (mQueue.size() == 0) { 45 return; 46 } 47 p = mQueue.removeFirst(); 48 r = p.first; 49 } 50 r.run(); 51 synchronized (mQueue) { 52 scheduleNextLocked(); 53 } 54 } 55 queueIdle()56 public boolean queueIdle() { 57 handleMessage(null); 58 return false; 59 } 60 } 61 62 private class IdleRunnable implements Runnable { 63 Runnable mRunnable; 64 IdleRunnable(Runnable r)65 IdleRunnable(Runnable r) { 66 mRunnable = r; 67 } 68 run()69 public void run() { 70 mRunnable.run(); 71 } 72 } 73 DeferredHandler()74 public DeferredHandler() { 75 } 76 77 /** Schedule runnable to run after everything that's on the queue right now. */ post(Runnable runnable)78 public void post(Runnable runnable) { 79 post(runnable, 0); 80 } post(Runnable runnable, int type)81 public void post(Runnable runnable, int type) { 82 synchronized (mQueue) { 83 mQueue.add(new Pair<Runnable, Integer>(runnable, type)); 84 if (mQueue.size() == 1) { 85 scheduleNextLocked(); 86 } 87 } 88 } 89 90 /** Schedule runnable to run when the queue goes idle. */ postIdle(final Runnable runnable)91 public void postIdle(final Runnable runnable) { 92 postIdle(runnable, 0); 93 } postIdle(final Runnable runnable, int type)94 public void postIdle(final Runnable runnable, int type) { 95 post(new IdleRunnable(runnable), type); 96 } 97 cancelRunnable(Runnable runnable)98 public void cancelRunnable(Runnable runnable) { 99 synchronized (mQueue) { 100 while (mQueue.remove(runnable)) { } 101 } 102 } cancelAllRunnablesOfType(int type)103 public void cancelAllRunnablesOfType(int type) { 104 synchronized (mQueue) { 105 ListIterator<Pair<Runnable, Integer>> iter = mQueue.listIterator(); 106 Pair<Runnable, Integer> p; 107 while (iter.hasNext()) { 108 p = iter.next(); 109 if (p.second == type) { 110 iter.remove(); 111 } 112 } 113 } 114 } 115 cancel()116 public void cancel() { 117 synchronized (mQueue) { 118 mQueue.clear(); 119 } 120 } 121 122 /** Runs all queued Runnables from the calling thread. */ flush()123 public void flush() { 124 LinkedList<Pair<Runnable, Integer>> queue = new LinkedList<Pair<Runnable, Integer>>(); 125 synchronized (mQueue) { 126 queue.addAll(mQueue); 127 mQueue.clear(); 128 } 129 for (Pair<Runnable, Integer> p : queue) { 130 p.first.run(); 131 } 132 } 133 scheduleNextLocked()134 void scheduleNextLocked() { 135 if (mQueue.size() > 0) { 136 Pair<Runnable, Integer> p = mQueue.getFirst(); 137 Runnable peek = p.first; 138 if (peek instanceof IdleRunnable) { 139 mMessageQueue.addIdleHandler(mHandler); 140 } else { 141 mHandler.sendEmptyMessage(1); 142 } 143 } 144 } 145 } 146 147