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 java.util.LinkedList; 20 21 import android.os.Handler; 22 import android.os.Looper; 23 import android.os.Message; 24 import android.os.MessageQueue; 25 26 /** 27 * Queue of things to run on a looper thread. Items posted with {@link #post} will not 28 * be actually enqued on the handler until after the last one has run, to keep from 29 * starving the thread. 30 * 31 * This class is fifo. 32 */ 33 public class DeferredHandler { 34 private LinkedList<Runnable> mQueue = new LinkedList<Runnable>(); 35 private MessageQueue mMessageQueue = Looper.myQueue(); 36 private Impl mHandler = new Impl(); 37 38 private class Impl extends Handler implements MessageQueue.IdleHandler { 39 public void handleMessage(Message msg) { 40 Runnable r; 41 synchronized (mQueue) { 42 if (mQueue.size() == 0) { 43 return; 44 } 45 r = mQueue.removeFirst(); 46 } 47 r.run(); 48 synchronized (mQueue) { 49 scheduleNextLocked(); 50 } 51 } 52 53 public boolean queueIdle() { 54 handleMessage(null); 55 return false; 56 } 57 } 58 59 private class IdleRunnable implements Runnable { 60 Runnable mRunnable; 61 62 IdleRunnable(Runnable r) { 63 mRunnable = r; 64 } 65 66 public void run() { 67 mRunnable.run(); 68 } 69 } 70 71 public DeferredHandler() { 72 } 73 74 /** Schedule runnable to run after everything that's on the queue right now. */ 75 public void post(Runnable runnable) { 76 synchronized (mQueue) { 77 mQueue.add(runnable); 78 if (mQueue.size() == 1) { 79 scheduleNextLocked(); 80 } 81 } 82 } 83 84 /** Schedule runnable to run when the queue goes idle. */ 85 public void postIdle(final Runnable runnable) { 86 post(new IdleRunnable(runnable)); 87 } 88 89 public void cancelRunnable(Runnable runnable) { 90 synchronized (mQueue) { 91 while (mQueue.remove(runnable)) { } 92 } 93 } 94 95 public void cancel() { 96 synchronized (mQueue) { 97 mQueue.clear(); 98 } 99 } 100 101 void scheduleNextLocked() { 102 if (mQueue.size() > 0) { 103 Runnable peek = mQueue.getFirst(); 104 if (peek instanceof IdleRunnable) { 105 mMessageQueue.addIdleHandler(mHandler); 106 } else { 107 mHandler.sendEmptyMessage(1); 108 } 109 } 110 } 111 } 112 113