diff --git a/quickstep/robolectric_tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java b/quickstep/robolectric_tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java index 5471e492ae..1386ac0371 100644 --- a/quickstep/robolectric_tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java +++ b/quickstep/robolectric_tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java @@ -41,20 +41,11 @@ import com.android.launcher3.icons.ComponentWithLabel; import com.android.launcher3.icons.IconCache; import com.android.launcher3.model.BgDataModel.FixedContainerItems; import com.android.launcher3.model.QuickstepModelDelegate.PredictorState; -import com.android.launcher3.model.data.AppInfo; -import com.android.launcher3.model.data.ItemInfo; -import com.android.launcher3.model.data.LauncherAppWidgetInfo; -import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.shadows.ShadowDeviceFlag; -import com.android.launcher3.util.ComponentKey; -import com.android.launcher3.util.IntArray; import com.android.launcher3.util.IntSet; -import com.android.launcher3.util.ItemInfoMatcher; import com.android.launcher3.util.LauncherModelHelper; -import com.android.launcher3.util.ViewOnDrawExecutor; import com.android.launcher3.widget.LauncherAppWidgetProviderInfo; import com.android.launcher3.widget.PendingAddWidgetInfo; -import com.android.launcher3.widget.model.WidgetsListBaseEntry; import org.junit.Before; import org.junit.Test; @@ -68,9 +59,6 @@ import org.robolectric.shadows.ShadowAppWidgetManager; import org.robolectric.shadows.ShadowPackageManager; import org.robolectric.util.ReflectionHelpers; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.stream.Collectors; @@ -243,60 +231,5 @@ public final class WidgetsPredicationUpdateTaskTest { public IntSet getPagesToBindSynchronously() { return IntSet.wrap(0); } - - @Override - public void clearPendingBinds() { } - - @Override - public void startBinding() { } - - @Override - public void bindItems(List shortcuts, boolean forceAnimateIcons) { } - - @Override - public void bindScreens(IntArray orderedScreenIds) { } - - @Override - public void finishFirstPageBind(ViewOnDrawExecutor executor) { } - - @Override - public void finishBindingItems(IntSet pagesBoundFirst) { } - - @Override - public void preAddApps() { } - - @Override - public void bindAppsAdded(IntArray newScreens, ArrayList addNotAnimated, - ArrayList addAnimated) { } - - @Override - public void bindIncrementalDownloadProgressUpdated(AppInfo app) { } - - @Override - public void bindWorkspaceItemsChanged(List updated) { } - - @Override - public void bindWidgetsRestored(ArrayList widgets) { } - - @Override - public void bindRestoreItemsChange(HashSet updates) { } - - @Override - public void bindWorkspaceComponentsRemoved(ItemInfoMatcher matcher) { } - - @Override - public void bindAllWidgets(List widgets) { } - - @Override - public void onPagesBoundSynchronously(IntSet pages) { } - - @Override - public void executeOnNextDraw(ViewOnDrawExecutor executor) { } - - @Override - public void bindDeepShortcutMap(HashMap deepShortcutMap) { } - - @Override - public void bindAllApplications(AppInfo[] apps, int flags) { } } } diff --git a/robolectric_tests/src/com/android/launcher3/model/ModelMultiCallbacksTest.java b/robolectric_tests/src/com/android/launcher3/model/ModelMultiCallbacksTest.java index 275cf81da0..07351fe65b 100644 --- a/robolectric_tests/src/com/android/launcher3/model/ModelMultiCallbacksTest.java +++ b/robolectric_tests/src/com/android/launcher3/model/ModelMultiCallbacksTest.java @@ -35,7 +35,7 @@ import com.android.launcher3.util.IntSet; import com.android.launcher3.util.LauncherLayoutBuilder; import com.android.launcher3.util.LauncherModelHelper; import com.android.launcher3.util.LooperExecutor; -import com.android.launcher3.util.ViewOnDrawExecutor; +import com.android.launcher3.util.RunnableList; import org.junit.Before; import org.junit.Test; @@ -106,14 +106,14 @@ public class ModelMultiCallbacksTest { // No effect on callbacks when removing an callback mModelHelper.getModel().removeCallbacks(cb2); waitForLoaderAndTempMainThread(); - assertNull(cb1.mDeferredExecutor); - assertNull(cb2.mDeferredExecutor); + assertNull(cb1.mPendingTasks); + assertNull(cb2.mPendingTasks); // Reloading only loads registered callbacks mModelHelper.getModel().startLoader(); waitForLoaderAndTempMainThread(); cb1.verifySynchronouslyBound(3); - assertNull(cb2.mDeferredExecutor); + assertNull(cb2.mPendingTasks); } @Test @@ -180,19 +180,15 @@ public class ModelMultiCallbacksTest { final List mItems = new ArrayList<>(); IntSet mPageToBindSync = IntSet.wrap(0); IntSet mPageBoundSync = new IntSet(); - ViewOnDrawExecutor mDeferredExecutor; + RunnableList mPendingTasks; AppInfo[] mAppInfos; MyCallbacks() { } @Override - public void onPagesBoundSynchronously(IntSet pages) { - mPageBoundSync = pages; - } - - @Override - public void executeOnNextDraw(ViewOnDrawExecutor executor) { - mDeferredExecutor = executor; + public void onInitialBindComplete(IntSet boundPages, RunnableList pendingTasks) { + mPageBoundSync = boundPages; + mPendingTasks = pendingTasks; } @Override @@ -213,19 +209,19 @@ public class ModelMultiCallbacksTest { public void reset() { mItems.clear(); mPageBoundSync = new IntSet(); - mDeferredExecutor = null; + mPendingTasks = null; mAppInfos = null; } public void verifySynchronouslyBound(int totalItems) { // Verify that the requested page is bound synchronously - assertEquals(mPageBoundSync, mPageToBindSync); + assertEquals(mPageToBindSync, mPageBoundSync); assertEquals(mItems.size(), 1); - assertEquals(mItems.get(0).screenId, mPageBoundSync); - assertNotNull(mDeferredExecutor); + assertEquals(IntSet.wrap(mItems.get(0).screenId), mPageBoundSync); + assertNotNull(mPendingTasks); // Verify that all other pages are bound properly - mDeferredExecutor.runAllTasks(); + mPendingTasks.executeAllAndDestroy(); assertEquals(mItems.size(), totalItems); } diff --git a/robolectric_tests/src/com/android/launcher3/util/LauncherUIHelper.java b/robolectric_tests/src/com/android/launcher3/util/LauncherUIHelper.java index fdddab49ce..caad40e260 100644 --- a/robolectric_tests/src/com/android/launcher3/util/LauncherUIHelper.java +++ b/robolectric_tests/src/com/android/launcher3/util/LauncherUIHelper.java @@ -81,7 +81,7 @@ public class LauncherUIHelper { doLayout(launcher); ViewOnDrawExecutor executor = ReflectionHelpers.getField(launcher, "mPendingExecutor"); if (executor != null) { - executor.runAllTasks(); + executor.markCompleted(); } return launcher; } diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 5a9257d636..5720a8cb34 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -118,6 +118,7 @@ import com.android.launcher3.allapps.AllAppsContainerView; import com.android.launcher3.allapps.AllAppsStore; import com.android.launcher3.allapps.AllAppsTransitionController; import com.android.launcher3.allapps.DiscoveryBounce; +import com.android.launcher3.anim.AnimatorListeners; import com.android.launcher3.anim.PropertyListBuilder; import com.android.launcher3.compat.AccessibilityManagerCompat; import com.android.launcher3.config.FeatureFlags; @@ -174,6 +175,7 @@ import com.android.launcher3.util.OnboardingPrefs; import com.android.launcher3.util.PackageManagerHelper; import com.android.launcher3.util.PackageUserKey; import com.android.launcher3.util.PendingRequestArgs; +import com.android.launcher3.util.RunnableList; import com.android.launcher3.util.SafeCloseable; import com.android.launcher3.util.SystemUiController; import com.android.launcher3.util.Themes; @@ -2060,7 +2062,7 @@ public class Launcher extends StatefulActivity implements Launche @Override public void clearPendingBinds() { if (mPendingExecutor != null) { - mPendingExecutor.markCompleted(); + mPendingExecutor.cancel(); mPendingExecutor = null; // We might have set this flag previously and forgot to clear it. @@ -2482,25 +2484,6 @@ public class Launcher extends StatefulActivity implements Launche return info; } - public void onPagesBoundSynchronously(IntSet pages) { - mSynchronouslyBoundPages = pages; - mWorkspace.setCurrentPage(pages.getArray().get(0)); - mPagesToBindSynchronously = new IntSet(); - } - - @Override - public void executeOnNextDraw(ViewOnDrawExecutor executor) { - clearPendingBinds(); - mPendingExecutor = executor; - if (!isInState(ALL_APPS)) { - mAppsView.getAppsStore().enableDeferUpdates(AllAppsStore.DEFER_UPDATES_NEXT_DRAW); - mPendingExecutor.execute(() -> mAppsView.getAppsStore().disableDeferUpdates( - AllAppsStore.DEFER_UPDATES_NEXT_DRAW)); - } - - executor.attachTo(this); - } - public void clearPendingExecutor(ViewOnDrawExecutor executor) { if (mPendingExecutor == executor) { mPendingExecutor = null; @@ -2508,22 +2491,31 @@ public class Launcher extends StatefulActivity implements Launche } @Override - public void finishFirstPageBind(final ViewOnDrawExecutor executor) { + public void onInitialBindComplete(IntSet boundPages, RunnableList pendingTasks) { + mSynchronouslyBoundPages = boundPages; + if (!boundPages.isEmpty()) { + mWorkspace.setCurrentPage(boundPages.getArray().get(0)); + } + mPagesToBindSynchronously = new IntSet(); + + clearPendingBinds(); + ViewOnDrawExecutor executor = new ViewOnDrawExecutor(pendingTasks); + mPendingExecutor = executor; + if (!isInState(ALL_APPS)) { + mAppsView.getAppsStore().enableDeferUpdates(AllAppsStore.DEFER_UPDATES_NEXT_DRAW); + pendingTasks.add(() -> mAppsView.getAppsStore().disableDeferUpdates( + AllAppsStore.DEFER_UPDATES_NEXT_DRAW)); + } + AlphaProperty property = mDragLayer.getAlphaProperty(ALPHA_INDEX_LAUNCHER_LOAD); if (property.getValue() < 1) { ObjectAnimator anim = ObjectAnimator.ofFloat(property, MultiValueAlpha.VALUE, 1); - if (executor != null) { - anim.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - executor.onLoadAnimationCompleted(); - } - }); - } + anim.addListener(AnimatorListeners.forEndCallback(executor::onLoadAnimationCompleted)); anim.start(); - } else if (executor != null) { + } else { executor.onLoadAnimationCompleted(); } + executor.attachTo(this); } /** diff --git a/src/com/android/launcher3/model/BaseLoaderResults.java b/src/com/android/launcher3/model/BaseLoaderResults.java index 12ee676b06..30755e398b 100644 --- a/src/com/android/launcher3/model/BaseLoaderResults.java +++ b/src/com/android/launcher3/model/BaseLoaderResults.java @@ -18,7 +18,9 @@ package com.android.launcher3.model; import static com.android.launcher3.model.ModelUtils.filterCurrentWorkspaceItems; import static com.android.launcher3.model.ModelUtils.sortWorkspaceItemsSpatially; +import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; +import android.os.Process; import android.util.Log; import com.android.launcher3.InvariantDeviceProfile; @@ -33,7 +35,7 @@ import com.android.launcher3.util.IntArray; import com.android.launcher3.util.IntSet; import com.android.launcher3.util.LooperExecutor; import com.android.launcher3.util.LooperIdleLock; -import com.android.launcher3.util.ViewOnDrawExecutor; +import com.android.launcher3.util.RunnableList; import java.util.ArrayList; import java.util.Collections; @@ -175,7 +177,6 @@ public abstract class BaseLoaderResults { currentScreenIndices = screenIndices; } - final boolean validFirstPage = !currentScreenIndices.isEmpty(); IntSet currentScreenIds = new IntSet(); currentScreenIndices.forEach( @@ -204,40 +205,25 @@ public abstract class BaseLoaderResults { // Bind workspace screens executeCallbacksTask(c -> c.bindScreens(mOrderedScreenIds), mUiExecutor); - Executor mainExecutor = mUiExecutor; // Load items on the current page. - bindWorkspaceItems(currentWorkspaceItems, mainExecutor); - bindAppWidgets(currentAppWidgets, mainExecutor); + bindWorkspaceItems(currentWorkspaceItems, mUiExecutor); + bindAppWidgets(currentAppWidgets, mUiExecutor); mExtraItems.forEach(item -> - executeCallbacksTask(c -> c.bindExtraContainerItems(item), mainExecutor)); + executeCallbacksTask(c -> c.bindExtraContainerItems(item), mUiExecutor)); - // In case of validFirstPage, only bind the first screen, and defer binding the - // remaining screens after first onDraw (and an optional the fade animation whichever - // happens later). - // This ensures that the first screen is immediately visible (eg. during rotation) - // In case of !validFirstPage, bind all pages one after other. + RunnableList pendingTasks = new RunnableList(); + Executor pendingExecutor = pendingTasks::add; + bindWorkspaceItems(otherWorkspaceItems, pendingExecutor); + bindAppWidgets(otherAppWidgets, pendingExecutor); + executeCallbacksTask(c -> c.finishBindingItems(currentScreenIndices), pendingExecutor); + pendingExecutor.execute( + () -> MODEL_EXECUTOR.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT)); - final Executor deferredExecutor = - validFirstPage ? new ViewOnDrawExecutor() : mainExecutor; - - executeCallbacksTask(c -> c.finishFirstPageBind( - validFirstPage ? (ViewOnDrawExecutor) deferredExecutor : null), mainExecutor); - - bindWorkspaceItems(otherWorkspaceItems, deferredExecutor); - bindAppWidgets(otherAppWidgets, deferredExecutor); - // Tell the workspace that we're done binding items - executeCallbacksTask(c -> c.finishBindingItems(currentScreenIndices), deferredExecutor); - - if (validFirstPage) { - executeCallbacksTask(c -> { - // We are loading synchronously, which means, some of the pages will be - // bound after first draw. Inform the mCallbacks that page binding is - // not complete, and schedule the remaining pages. - c.onPagesBoundSynchronously(currentScreenIndices); - c.executeOnNextDraw((ViewOnDrawExecutor) deferredExecutor); - - }, mUiExecutor); - } + executeCallbacksTask( + c -> { + MODEL_EXECUTOR.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); + c.onInitialBindComplete(currentScreenIndices, pendingTasks); + }, mUiExecutor); } private void bindWorkspaceItems( diff --git a/src/com/android/launcher3/model/BgDataModel.java b/src/com/android/launcher3/model/BgDataModel.java index 0740a30f21..ba825ca300 100644 --- a/src/com/android/launcher3/model/BgDataModel.java +++ b/src/com/android/launcher3/model/BgDataModel.java @@ -49,7 +49,7 @@ import com.android.launcher3.util.IntArray; import com.android.launcher3.util.IntSet; import com.android.launcher3.util.IntSparseArrayMap; import com.android.launcher3.util.ItemInfoMatcher; -import com.android.launcher3.util.ViewOnDrawExecutor; +import com.android.launcher3.util.RunnableList; import com.android.launcher3.widget.model.WidgetsListBaseEntry; import java.io.FileDescriptor; @@ -462,35 +462,41 @@ public class BgDataModel { * Returns an IntSet of page numbers to bind first, synchronously if possible * or an empty IntSet */ - IntSet getPagesToBindSynchronously(); - void clearPendingBinds(); - void startBinding(); - void bindItems(List shortcuts, boolean forceAnimateIcons); - void bindScreens(IntArray orderedScreenIds); - void finishFirstPageBind(ViewOnDrawExecutor executor); - void finishBindingItems(IntSet pagesBoundFirst); - void preAddApps(); - void bindAppsAdded(IntArray newScreens, - ArrayList addNotAnimated, ArrayList addAnimated); + default IntSet getPagesToBindSynchronously() { + return new IntSet(); + } + + default void clearPendingBinds() { } + default void startBinding() { } + + default void bindItems(List shortcuts, boolean forceAnimateIcons) { } + default void bindScreens(IntArray orderedScreenIds) { } + default void finishBindingItems(IntSet pagesBoundFirst) { } + default void preAddApps() { } + default void bindAppsAdded(IntArray newScreens, + ArrayList addNotAnimated, ArrayList addAnimated) { } /** * Binds updated incremental download progress */ - void bindIncrementalDownloadProgressUpdated(AppInfo app); - void bindWorkspaceItemsChanged(List updated); - void bindWidgetsRestored(ArrayList widgets); - void bindRestoreItemsChange(HashSet updates); - void bindWorkspaceComponentsRemoved(ItemInfoMatcher matcher); - void bindAllWidgets(List widgets); - void onPagesBoundSynchronously(IntSet pages); - void executeOnNextDraw(ViewOnDrawExecutor executor); - void bindDeepShortcutMap(HashMap deepShortcutMap); + default void bindIncrementalDownloadProgressUpdated(AppInfo app) { } + default void bindWorkspaceItemsChanged(List updated) { } + default void bindWidgetsRestored(ArrayList widgets) { } + default void bindRestoreItemsChange(HashSet updates) { } + default void bindWorkspaceComponentsRemoved(ItemInfoMatcher matcher) { } + default void bindAllWidgets(List widgets) { } + + default void onInitialBindComplete(IntSet boundPages, RunnableList pendingTasks) { + pendingTasks.executeAllAndDestroy(); + } + + default void bindDeepShortcutMap(HashMap deepShortcutMap) { } /** * Binds extra item provided any external source */ default void bindExtraContainerItems(FixedContainerItems item) { } - void bindAllApplications(AppInfo[] apps, int flags); + default void bindAllApplications(AppInfo[] apps, int flags) { } } } diff --git a/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java b/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java index b271a6a7ce..1a96c2311c 100644 --- a/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java +++ b/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java @@ -35,23 +35,13 @@ import com.android.launcher3.model.BgDataModel; import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.ItemInfoWithIcon; -import com.android.launcher3.model.data.LauncherAppWidgetInfo; -import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.popup.PopupContainerWithArrow; import com.android.launcher3.popup.PopupDataProvider; import com.android.launcher3.util.ComponentKey; -import com.android.launcher3.util.IntArray; -import com.android.launcher3.util.IntSet; -import com.android.launcher3.util.ItemInfoMatcher; import com.android.launcher3.util.Themes; -import com.android.launcher3.util.ViewOnDrawExecutor; import com.android.launcher3.views.BaseDragLayer; -import com.android.launcher3.widget.model.WidgetsListBaseEntry; -import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; -import java.util.List; /** * Launcher activity for secondary displays @@ -175,68 +165,11 @@ public class SecondaryDisplayLauncher extends BaseDraggingActivity return mDragLayer; } - @Override - public IntSet getPagesToBindSynchronously() { - return new IntSet(); - } - - @Override - public void clearPendingBinds() { } - - @Override - public void startBinding() { } - - @Override - public void bindItems(List shortcuts, boolean forceAnimateIcons) { } - - @Override - public void bindScreens(IntArray orderedScreenIds) { } - - @Override - public void finishFirstPageBind(ViewOnDrawExecutor executor) { - if (executor != null) { - executor.onLoadAnimationCompleted(); - } - } - - @Override - public void finishBindingItems(IntSet pagesBoundFirst) { } - - @Override - public void preAddApps() { } - - @Override - public void bindAppsAdded(IntArray newScreens, ArrayList addNotAnimated, - ArrayList addAnimated) { } - @Override public void bindIncrementalDownloadProgressUpdated(AppInfo app) { mAppsView.getAppsStore().updateProgressBar(app); } - @Override - public void bindWorkspaceItemsChanged(List updated) { } - - @Override - public void bindWidgetsRestored(ArrayList widgets) { } - - @Override - public void bindRestoreItemsChange(HashSet updates) { } - - @Override - public void bindWorkspaceComponentsRemoved(ItemInfoMatcher matcher) { } - - @Override - public void bindAllWidgets(List widgets) { } - - @Override - public void onPagesBoundSynchronously(IntSet pages) { } - - @Override - public void executeOnNextDraw(ViewOnDrawExecutor executor) { - executor.attachTo(getDragLayer(), false, null); - } - /** * Called when apps-button is clicked */ diff --git a/src/com/android/launcher3/util/ViewOnDrawExecutor.java b/src/com/android/launcher3/util/ViewOnDrawExecutor.java index 82e24c24f5..5d902917cd 100644 --- a/src/com/android/launcher3/util/ViewOnDrawExecutor.java +++ b/src/com/android/launcher3/util/ViewOnDrawExecutor.java @@ -16,28 +16,21 @@ package com.android.launcher3.util; -import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; - -import android.os.Process; import android.view.View; import android.view.View.OnAttachStateChangeListener; import android.view.ViewTreeObserver.OnDrawListener; -import androidx.annotation.VisibleForTesting; - import com.android.launcher3.Launcher; -import java.util.ArrayList; -import java.util.concurrent.Executor; import java.util.function.Consumer; /** * An executor which runs all the tasks after the first onDraw is called on the target view. */ -public class ViewOnDrawExecutor implements Executor, OnDrawListener, Runnable, +public class ViewOnDrawExecutor implements OnDrawListener, Runnable, OnAttachStateChangeListener { - private final ArrayList mTasks = new ArrayList<>(); + private final RunnableList mTasks; private Consumer mOnClearCallback; private View mAttachedView; @@ -46,22 +39,16 @@ public class ViewOnDrawExecutor implements Executor, OnDrawListener, Runnable, private boolean mLoadAnimationCompleted; private boolean mFirstDrawCompleted; - public void attachTo(Launcher launcher) { - attachTo(launcher.getWorkspace(), true /* waitForLoadAnimation */, - launcher::clearPendingExecutor); + private boolean mCancelled; + + public ViewOnDrawExecutor(RunnableList tasks) { + mTasks = tasks; } - /** - * Attached the executor to the existence of the view - */ - public void attachTo(View attachedView, boolean waitForLoadAnimation, - Consumer onClearCallback) { - mOnClearCallback = onClearCallback; - mAttachedView = attachedView; + public void attachTo(Launcher launcher) { + mOnClearCallback = launcher::clearPendingExecutor; + mAttachedView = launcher.getWorkspace(); mAttachedView.addOnAttachStateChangeListener(this); - if (!waitForLoadAnimation) { - mLoadAnimationCompleted = true; - } if (mAttachedView.isAttachedToWindow()) { attachObserver(); @@ -74,12 +61,6 @@ public class ViewOnDrawExecutor implements Executor, OnDrawListener, Runnable, } } - @Override - public void execute(Runnable command) { - mTasks.add(command); - MODEL_EXECUTOR.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); - } - @Override public void onViewAttachedToWindow(View v) { attachObserver(); @@ -105,12 +86,17 @@ public class ViewOnDrawExecutor implements Executor, OnDrawListener, Runnable, public void run() { // Post the pending tasks after both onDraw and onLoadAnimationCompleted have been called. if (mLoadAnimationCompleted && mFirstDrawCompleted && !mCompleted) { - runAllTasks(); + markCompleted(); } } + /** + * Executes all tasks immediately + */ public void markCompleted() { - mTasks.clear(); + if (!mCancelled) { + mTasks.executeAllAndDestroy(); + } mCompleted = true; if (mAttachedView != null) { mAttachedView.getViewTreeObserver().removeOnDrawListener(this); @@ -119,21 +105,10 @@ public class ViewOnDrawExecutor implements Executor, OnDrawListener, Runnable, if (mOnClearCallback != null) { mOnClearCallback.accept(this); } - MODEL_EXECUTOR.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); } - protected boolean isCompleted() { - return mCompleted; - } - - /** - * Executes all tasks immediately - */ - @VisibleForTesting - public void runAllTasks() { - for (final Runnable r : mTasks) { - r.run(); - } + public void cancel() { + mCancelled = true; markCompleted(); } }