Home | History | Annotate | Download | only in util
      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.os.Process;
     20 import android.view.View;
     21 import android.view.View.OnAttachStateChangeListener;
     22 import android.view.ViewTreeObserver.OnDrawListener;
     23 
     24 import com.android.launcher3.Launcher;
     25 import com.android.launcher3.LauncherModel;
     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 
     38     private Launcher mLauncher;
     39     private View mAttachedView;
     40     private boolean mCompleted;
     41 
     42     private boolean mLoadAnimationCompleted;
     43     private boolean mFirstDrawCompleted;
     44 
     45     public void attachTo(Launcher launcher) {
     46         attachTo(launcher, launcher.getWorkspace(), true /* waitForLoadAnimation */);
     47     }
     48 
     49     public void attachTo(Launcher launcher, View attachedView, boolean waitForLoadAnimation) {
     50         mLauncher = launcher;
     51         mAttachedView = attachedView;
     52         mAttachedView.addOnAttachStateChangeListener(this);
     53         if (!waitForLoadAnimation) {
     54             mLoadAnimationCompleted = true;
     55         }
     56 
     57         attachObserver();
     58     }
     59 
     60     private void attachObserver() {
     61         if (!mCompleted) {
     62             mAttachedView.getViewTreeObserver().addOnDrawListener(this);
     63         }
     64     }
     65 
     66     @Override
     67     public void execute(Runnable command) {
     68         mTasks.add(command);
     69         LauncherModel.setWorkerPriority(Process.THREAD_PRIORITY_BACKGROUND);
     70     }
     71 
     72     @Override
     73     public void onViewAttachedToWindow(View v) {
     74         attachObserver();
     75     }
     76 
     77     @Override
     78     public void onViewDetachedFromWindow(View v) {}
     79 
     80     @Override
     81     public void onDraw() {
     82         mFirstDrawCompleted = true;
     83         mAttachedView.post(this);
     84     }
     85 
     86     public void onLoadAnimationCompleted() {
     87         mLoadAnimationCompleted = true;
     88         if (mAttachedView != null) {
     89             mAttachedView.post(this);
     90         }
     91     }
     92 
     93     @Override
     94     public void run() {
     95         // Post the pending tasks after both onDraw and onLoadAnimationCompleted have been called.
     96         if (mLoadAnimationCompleted && mFirstDrawCompleted && !mCompleted) {
     97             runAllTasks();
     98         }
     99     }
    100 
    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         LauncherModel.setWorkerPriority(Process.THREAD_PRIORITY_DEFAULT);
    112     }
    113 
    114     protected boolean isCompleted() {
    115         return mCompleted;
    116     }
    117 
    118     protected void runAllTasks() {
    119         for (final Runnable r : mTasks) {
    120             r.run();
    121         }
    122         markCompleted();
    123     }
    124 }
    125