• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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