1/*
2 * Copyright (C) 2012 Google Inc.
3 * Licensed to The Android Open Source Project.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package com.android.mail.ui;
19
20import android.app.Activity;
21import android.app.FragmentTransaction;
22import android.os.Handler;
23
24import com.android.mail.utils.LogTag;
25import com.android.mail.utils.LogUtils;
26
27import java.util.concurrent.atomic.AtomicInteger;
28
29/**
30 * A thin wrapper of {@link Handler} to run a callback in UI thread. Any callback posted to this
31 * handler is guarantee to run inside {@link Activity} life cycle. However, it can be dropped if the
32 * {@link Activity} has been stopped. This handler is safe to use with {@link FragmentTransaction}.
33 *
34 * @author phamm
35 */
36public class UiHandler {
37    private final Handler mHandler = new Handler();
38    private boolean mEnabled = true;
39    private final static String LOG_TAG = LogTag.getLogTag();
40
41    /** Number of {@link Runnable} in the queue. */
42    private AtomicInteger mCount = new AtomicInteger(0);
43
44    public void post(final Runnable r) {
45        if (mEnabled) {
46            mCount.incrementAndGet();
47            mHandler.post(new Runnable() {
48                @Override
49                public void run() {
50                    mCount.decrementAndGet();
51                    r.run();
52                }
53            });
54        } else {
55            LogUtils.d(LOG_TAG, "UiHandler is disabled in post(). Dropping Runnable.");
56        }
57    }
58
59    public void postDelayed(final Runnable r, long delayMillis) {
60        if (mEnabled) {
61            mCount.incrementAndGet();
62            mHandler.postDelayed(new Runnable() {
63                @Override
64                public void run() {
65                    mCount.decrementAndGet();
66                    r.run();
67                }
68            }, delayMillis);
69        } else {
70            LogUtils.d(LOG_TAG, "UiHandler is disabled in postDelayed(). Dropping Runnable.");
71        }
72    }
73
74    public void removeCallbacks(Runnable r) {
75        mHandler.removeCallbacks(r);
76    }
77
78    public void setEnabled(boolean enabled) {
79        mEnabled = enabled;
80        if (!mEnabled) {
81            int count = mCount.getAndSet(0);
82            if (count > 0) {
83                LogUtils.e(LOG_TAG, "Disable UiHandler. Dropping %d Runnables.", count);
84            }
85            mHandler.removeCallbacksAndMessages(null);
86        }
87    }
88
89    /**
90     * @return whether the {@link UiHandler} is enabled. It's safe to edit UI if the
91     *         {@link UiHandler} is enabled.
92     */
93    public boolean isEnabled() {
94        return mEnabled;
95    }
96}