1 /* 2 * Copyright (C) 2011 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.emailcommon.utility; 18 19 import com.google.common.annotations.VisibleForTesting; 20 21 import android.os.Handler; 22 23 import java.util.ArrayList; 24 import java.util.LinkedList; 25 26 /** 27 * Class that helps post {@link Runnable}s to a {@link Handler}, and cancel pending ones 28 * at once. 29 */ 30 public class DelayedOperations { 31 private final Handler mHandler; 32 33 @VisibleForTesting 34 final LinkedList<QueuedOperation> mPendingOperations = new LinkedList<QueuedOperation>(); 35 36 private class QueuedOperation implements Runnable { 37 private final Runnable mActualRannable; 38 QueuedOperation(Runnable actualRannable)39 public QueuedOperation(Runnable actualRannable) { 40 mActualRannable = actualRannable; 41 } 42 43 @Override run()44 public void run() { 45 mPendingOperations.remove(this); 46 mActualRannable.run(); 47 } 48 cancel()49 public void cancel() { 50 mPendingOperations.remove(this); 51 cancelRunnable(this); 52 } 53 } 54 DelayedOperations(Handler handler)55 public DelayedOperations(Handler handler) { 56 mHandler = handler; 57 } 58 59 /** 60 * Post a {@link Runnable} to the handler. Equivalent to {@link Handler#post(Runnable)}. 61 */ post(Runnable r)62 public void post(Runnable r) { 63 final QueuedOperation qo = new QueuedOperation(r); 64 mPendingOperations.add(qo); 65 postRunnable(qo); 66 } 67 68 /** 69 * Cancel a runnable that's been posted with {@link #post(Runnable)}. 70 * 71 * Equivalent to {@link Handler#removeCallbacks(Runnable)}. 72 */ removeCallbacks(Runnable r)73 public void removeCallbacks(Runnable r) { 74 QueuedOperation found = null; 75 for (QueuedOperation qo : mPendingOperations) { 76 if (qo.mActualRannable == r) { 77 found = qo; 78 break; 79 } 80 } 81 if (found != null) { 82 found.cancel(); 83 } 84 } 85 86 /** 87 * Cancel all pending {@link Runnable}s. 88 */ removeCallbacks()89 public void removeCallbacks() { 90 // To avoid ConcurrentModificationException 91 final ArrayList<QueuedOperation> temp = new ArrayList<QueuedOperation>(mPendingOperations); 92 for (QueuedOperation qo : temp) { 93 qo.cancel(); 94 } 95 } 96 97 /** Overridden by test, as Handler is not mockable. */ postRunnable(Runnable r)98 void postRunnable(Runnable r) { 99 mHandler.post(r); 100 } 101 102 /** Overridden by test, as Handler is not mockable. */ cancelRunnable(Runnable r)103 void cancelRunnable(Runnable r) { 104 mHandler.removeCallbacks(r); 105 } 106 } 107