DrawIdler.java revision 144bfe739b93afdee0a1700a34806b0b287e5887
1package com.android.mail.utils;
2
3import android.os.Handler;
4import android.view.View;
5import android.view.ViewTreeObserver;
6
7/**
8 * Given a View to monitor draws on, an instance of this class will notify a listener of state
9 * changes between {@link #STATE_ACTIVE} and {@link #STATE_IDLE}.
10 * <p>
11 * Any drawing will instantly trigger {@link #STATE_ACTIVE}. {@link #STATE_IDLE} is only
12 * subsequently triggered if {@link #IDLE_WINDOW_MS} continuous milliseconds elapse with zero draws.
13 */
14public class DrawIdler {
15
16    public static final int STATE_IDLE = 0;
17    public static final int STATE_ACTIVE = 1;
18
19    private static final int IDLE_WINDOW_MS = 100;
20
21    private int mState = STATE_IDLE;
22
23    private View mRoot;
24    private IdleListener mListener;
25    private final IdleReader mIdleReader = new IdleReader();
26    private final Handler mHandler = new Handler();
27
28    public interface IdleListener {
29        void onStateChanged(DrawIdler idler, int newState);
30    }
31
32    public void setListener(IdleListener listener) {
33        mListener = listener;
34        if (mListener != null) {
35            mListener.onStateChanged(this, mState);
36        }
37    }
38
39    public void setRootView(View rootView) {
40        if (mRoot == rootView) {
41            return;
42        } else if (mRoot != null) {
43            mRoot.getViewTreeObserver().removeOnPreDrawListener(mIdleReader);
44        }
45
46        mRoot = rootView;
47
48        if (mRoot != null) {
49            mRoot.getViewTreeObserver().addOnPreDrawListener(mIdleReader);
50        }
51    }
52
53    public int getCurrentState() {
54        return mState;
55    }
56
57    private void setState(int newState) {
58        if (mState == newState) {
59            return;
60        }
61        mState = newState;
62        if (mListener != null) {
63            mListener.onStateChanged(this, newState);
64        }
65    }
66
67    // this inner class keeps implementation details private
68    // (we use OnPreDrawListener instead of OnDrawListener because the latter is only JB+)
69    private class IdleReader implements Runnable, ViewTreeObserver.OnPreDrawListener {
70
71        @Override
72        public void run() {
73            setState(STATE_IDLE);
74        }
75
76        @Override
77        public boolean onPreDraw() {
78            setState(STATE_ACTIVE);
79            mHandler.removeCallbacks(this);
80            mHandler.postDelayed(this, IDLE_WINDOW_MS);
81            return true; // always allow the draw; we're only here to observe
82        }
83
84    }
85
86}
87