16b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki/* 26b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki * Copyright (C) 2011 The Android Open Source Project 36b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki * 46b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki * Licensed under the Apache License, Version 2.0 (the "License"); 56b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki * you may not use this file except in compliance with the License. 66b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki * You may obtain a copy of the License at 76b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki * 86b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki * http://www.apache.org/licenses/LICENSE-2.0 96b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki * 106b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki * Unless required by applicable law or agreed to in writing, software 116b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki * distributed under the License is distributed on an "AS IS" BASIS, 126b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki * See the License for the specific language governing permissions and 146b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki * limitations under the License. 156b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki */ 166b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki 176b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onukipackage com.android.emailcommon.utility; 186b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki 196b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onukiimport com.google.common.annotations.VisibleForTesting; 206b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki 216b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onukiimport android.os.Handler; 226b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki 236b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onukiimport java.util.ArrayList; 246b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onukiimport java.util.LinkedList; 256b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki 266b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki/** 276b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki * Class that helps post {@link Runnable}s to a {@link Handler}, and cancel pending ones 286b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki * at once. 296b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki */ 306b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onukipublic class DelayedOperations { 316b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki private final Handler mHandler; 326b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki 336b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki @VisibleForTesting 346b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki final LinkedList<QueuedOperation> mPendingOperations = new LinkedList<QueuedOperation>(); 356b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki 366b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki private class QueuedOperation implements Runnable { 376b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki private final Runnable mActualRannable; 386b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki 396b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki public QueuedOperation(Runnable actualRannable) { 406b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki mActualRannable = actualRannable; 416b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki } 426b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki 436b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki @Override 446b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki public void run() { 456b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki mPendingOperations.remove(this); 466b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki mActualRannable.run(); 476b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki } 486b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki 496b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki public void cancel() { 506b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki mPendingOperations.remove(this); 516b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki cancelRunnable(this); 526b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki } 536b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki } 546b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki 556b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki public DelayedOperations(Handler handler) { 566b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki mHandler = handler; 576b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki } 586b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki 596b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki /** 606b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki * Post a {@link Runnable} to the handler. Equivalent to {@link Handler#post(Runnable)}. 616b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki */ 626b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki public void post(Runnable r) { 636b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki final QueuedOperation qo = new QueuedOperation(r); 646b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki mPendingOperations.add(qo); 656b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki postRunnable(qo); 666b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki } 676b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki 686b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki /** 696b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki * Cancel a runnable that's been posted with {@link #post(Runnable)}. 706b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki * 716b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki * Equivalent to {@link Handler#removeCallbacks(Runnable)}. 726b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki */ 736b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki public void removeCallbacks(Runnable r) { 746b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki QueuedOperation found = null; 756b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki for (QueuedOperation qo : mPendingOperations) { 766b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki if (qo.mActualRannable == r) { 776b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki found = qo; 786b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki break; 796b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki } 806b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki } 816b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki if (found != null) { 826b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki found.cancel(); 836b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki } 846b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki } 856b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki 866b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki /** 876b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki * Cancel all pending {@link Runnable}s. 886b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki */ 896b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki public void removeCallbacks() { 906b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki // To avoid ConcurrentModificationException 916b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki final ArrayList<QueuedOperation> temp = new ArrayList<QueuedOperation>(mPendingOperations); 926b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki for (QueuedOperation qo : temp) { 936b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki qo.cancel(); 946b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki } 956b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki } 966b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki 976b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki /** Overridden by test, as Handler is not mockable. */ 986b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki void postRunnable(Runnable r) { 996b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki mHandler.post(r); 1006b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki } 1016b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki 1026b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki /** Overridden by test, as Handler is not mockable. */ 1036b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki void cancelRunnable(Runnable r) { 1046b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki mHandler.removeCallbacks(r); 1056b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki } 1066b968c1dce3ba78680d968e04fc6f59bbbb22073Makoto Onuki} 107