Listenable.java revision 81308a22b0f64c6667f6c23adee9da520415bcb6
1/*
2 * Copyright (C) 2014 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
17package com.android.camera.async;
18
19import com.android.camera.util.Callback;
20
21/**
22 * Wraps {@link ConcurrentState} with {@link #setCallback} semantics which
23 * overwrite any existing callback.
24 */
25public class Listenable<T> implements SafeCloseable {
26    private final ConcurrentState<T> mState;
27    private final MainThread mMainThread;
28    private final Object mLock;
29    private boolean mClosed;
30    private SafeCloseable mExistingCallbackHandle;
31
32    public Listenable(ConcurrentState<T> state, MainThread mainThread) {
33        mState = state;
34        mMainThread = mainThread;
35        mLock = new Object();
36        mClosed = false;
37        mExistingCallbackHandle = null;
38    }
39
40    /**
41     * Sets the callback, removing any existing callback first.
42     */
43    public void setCallback(final Callback<T> callback) {
44        synchronized (mLock) {
45            if (mClosed) {
46                return;
47            }
48            if (mExistingCallbackHandle != null) {
49                // Unregister any existing callback
50                mExistingCallbackHandle.close();
51            }
52            mExistingCallbackHandle = mState.addCallback(new Runnable() {
53                @Override
54                public void run() {
55                    callback.onCallback(mState.get());
56                }
57            }, mMainThread);
58        }
59    }
60
61    /**
62     * Removes any existing callbacks.
63     */
64    public void clear() {
65        synchronized (mLock) {
66            mClosed = true;
67            if (mExistingCallbackHandle != null) {
68                // Unregister any existing callback
69                mExistingCallbackHandle.close();
70            }
71        }
72    }
73
74    /**
75     * Removes any existing callbacks.  Once closed, no more callbacks will be registered.
76     */
77    @Override
78    public void close() {
79        synchronized (mLock) {
80            mClosed = true;
81            clear();
82        }
83    }
84}
85