ContentObserver.java revision 86de0590b94bcce27e3038c27464bed510bb564a
1/*
2 * Copyright (C) 2007 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 android.database;
18
19import android.os.Handler;
20
21/**
22 * Receives call backs for changes to content.
23 * Must be implemented by objects which are added to a {@link ContentObservable}.
24 */
25public abstract class ContentObserver {
26    private final Object mLock = new Object();
27    private Transport mTransport; // guarded by mLock
28
29    Handler mHandler;
30
31    /**
32     * Creates a content observer.
33     *
34     * @param handler The handler to run {@link #onChange} on, or null if none.
35     */
36    public ContentObserver(Handler handler) {
37        mHandler = handler;
38    }
39
40    /**
41     * Gets access to the binder transport object. Not for public consumption.
42     *
43     * {@hide}
44     */
45    public IContentObserver getContentObserver() {
46        synchronized (mLock) {
47            if (mTransport == null) {
48                mTransport = new Transport(this);
49            }
50            return mTransport;
51        }
52    }
53
54    /**
55     * Gets access to the binder transport object, and unlinks the transport object
56     * from the ContentObserver. Not for public consumption.
57     *
58     * {@hide}
59     */
60    public IContentObserver releaseContentObserver() {
61        synchronized (mLock) {
62            final Transport oldTransport = mTransport;
63            if (oldTransport != null) {
64                oldTransport.releaseContentObserver();
65                mTransport = null;
66            }
67            return oldTransport;
68        }
69    }
70
71    /**
72     * Returns true if this observer is interested receiving self-change notifications.
73     *
74     * Subclasses should override this method to indicate whether the observer
75     * is interested in receiving notifications for changes that it made to the
76     * content itself.
77     *
78     * @return True if self-change notifications should be delivered to the observer.
79     */
80    public boolean deliverSelfNotifications() {
81        return false;
82    }
83
84    /**
85     * This method is called when a content change occurs.
86     *
87     * @param selfChange True if this is a self-change notification.
88     */
89    public void onChange(boolean selfChange) {
90        // Do nothing.  Subclass should override.
91    }
92
93    /**
94     * Dispatches a change notification to the observer.
95     *
96     * If a {@link Handler} was supplied to the {@link ContentObserver} constructor,
97     * then a call to the {@link #onChange} method is posted to the handler's message queue.
98     * Otherwise, the {@link #onChange} method is invoked immediately on this thread.
99     *
100     * @param selfChange True if this is a self-change notification.
101     */
102    public final void dispatchChange(boolean selfChange) {
103        if (mHandler == null) {
104            onChange(selfChange);
105        } else {
106            mHandler.post(new NotificationRunnable(selfChange));
107        }
108    }
109
110    private final class NotificationRunnable implements Runnable {
111        private final boolean mSelf;
112
113        public NotificationRunnable(boolean self) {
114            mSelf = self;
115        }
116
117        @Override
118        public void run() {
119            ContentObserver.this.onChange(mSelf);
120        }
121    }
122
123    private static final class Transport extends IContentObserver.Stub {
124        private ContentObserver mContentObserver;
125
126        public Transport(ContentObserver contentObserver) {
127            mContentObserver = contentObserver;
128        }
129
130        @Override
131        public void onChange(boolean selfChange) {
132            ContentObserver contentObserver = mContentObserver;
133            if (contentObserver != null) {
134                contentObserver.dispatchChange(selfChange);
135            }
136        }
137
138        public void releaseContentObserver() {
139            mContentObserver = null;
140        }
141    }
142}
143