1 /** 2 * Copyright (C) 2015 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.launcher3.util; 18 19 import android.util.Log; 20 import android.view.View; 21 import android.view.View.OnAttachStateChangeListener; 22 import android.view.ViewTreeObserver.OnDrawListener; 23 24 import com.android.launcher3.DeferredHandler; 25 import com.android.launcher3.Launcher; 26 27 import java.util.ArrayList; 28 import java.util.concurrent.Executor; 29 30 /** 31 * An executor which runs all the tasks after the first onDraw is called on the target view. 32 */ 33 public class ViewOnDrawExecutor implements Executor, OnDrawListener, Runnable, 34 OnAttachStateChangeListener { 35 36 private final ArrayList<Runnable> mTasks = new ArrayList<>(); 37 private final DeferredHandler mHandler; 38 39 private Launcher mLauncher; 40 private View mAttachedView; 41 private boolean mCompleted; 42 43 private boolean mLoadAnimationCompleted; 44 private boolean mFirstDrawCompleted; 45 ViewOnDrawExecutor(DeferredHandler handler)46 public ViewOnDrawExecutor(DeferredHandler handler) { 47 mHandler = handler; 48 } 49 attachTo(Launcher launcher)50 public void attachTo(Launcher launcher) { 51 mLauncher = launcher; 52 mAttachedView = launcher.getWorkspace(); 53 mAttachedView.addOnAttachStateChangeListener(this); 54 55 attachObserver(); 56 } 57 attachObserver()58 private void attachObserver() { 59 if (!mCompleted) { 60 mAttachedView.getViewTreeObserver().addOnDrawListener(this); 61 } 62 } 63 64 @Override execute(Runnable command)65 public void execute(Runnable command) { 66 mTasks.add(command); 67 } 68 69 @Override onViewAttachedToWindow(View v)70 public void onViewAttachedToWindow(View v) { 71 attachObserver(); 72 } 73 74 @Override onViewDetachedFromWindow(View v)75 public void onViewDetachedFromWindow(View v) { } 76 77 @Override onDraw()78 public void onDraw() { 79 mFirstDrawCompleted = true; 80 mAttachedView.post(this); 81 } 82 onLoadAnimationCompleted()83 public void onLoadAnimationCompleted() { 84 mLoadAnimationCompleted = true; 85 if (mAttachedView != null) { 86 mAttachedView.post(this); 87 } 88 } 89 90 @Override run()91 public void run() { 92 // Post the pending tasks after both onDraw and onLoadAnimationCompleted have been called. 93 if (mLoadAnimationCompleted && mFirstDrawCompleted && !mCompleted) { 94 for (final Runnable r : mTasks) { 95 mHandler.post(r); 96 } 97 markCompleted(); 98 } 99 } 100 markCompleted()101 public void markCompleted() { 102 mTasks.clear(); 103 mCompleted = true; 104 if (mAttachedView != null) { 105 mAttachedView.getViewTreeObserver().removeOnDrawListener(this); 106 mAttachedView.removeOnAttachStateChangeListener(this); 107 } 108 if (mLauncher != null) { 109 mLauncher.clearPendingExecutor(this); 110 } 111 } 112 } 113