ContentObserver.java revision 54b6cfa9a9e5b861a9930af873580d6dc20f773c
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. Must be implemented by objects which are added
23 * to a {@link ContentObservable}.
24 */
25public abstract class ContentObserver {
26
27    private Transport mTransport;
28
29    // Protects mTransport
30    private Object lock = new Object();
31
32    /* package */ Handler mHandler;
33
34    private final class NotificationRunnable implements Runnable {
35
36        private boolean mSelf;
37
38        public NotificationRunnable(boolean self) {
39            mSelf = self;
40        }
41
42        public void run() {
43            ContentObserver.this.onChange(mSelf);
44        }
45    }
46
47    private static final class Transport extends IContentObserver.Stub {
48        ContentObserver mContentObserver;
49
50        public Transport(ContentObserver contentObserver) {
51            mContentObserver = contentObserver;
52        }
53
54        public boolean deliverSelfNotifications() {
55            ContentObserver contentObserver = mContentObserver;
56            if (contentObserver != null) {
57                return contentObserver.deliverSelfNotifications();
58            }
59            return false;
60        }
61
62        public void onChange(boolean selfChange) {
63            ContentObserver contentObserver = mContentObserver;
64            if (contentObserver != null) {
65                contentObserver.dispatchChange(selfChange);
66            }
67        }
68
69        public void releaseContentObserver() {
70            mContentObserver = null;
71        }
72    }
73
74    /**
75     * onChange() will happen on the provider Handler.
76     *
77     * @param handler The handler to run {@link #onChange} on.
78     */
79    public ContentObserver(Handler handler) {
80        mHandler = handler;
81    }
82
83    /**
84     * Gets access to the binder transport object. Not for public consumption.
85     *
86     * {@hide}
87     */
88    public IContentObserver getContentObserver() {
89        synchronized(lock) {
90            if (mTransport == null) {
91                mTransport = new Transport(this);
92            }
93            return mTransport;
94        }
95    }
96
97    /**
98     * Gets access to the binder transport object, and unlinks the transport object
99     * from the ContentObserver. Not for public consumption.
100     *
101     * {@hide}
102     */
103    public IContentObserver releaseContentObserver() {
104        synchronized(lock) {
105            Transport oldTransport = mTransport;
106            if (oldTransport != null) {
107                oldTransport.releaseContentObserver();
108                mTransport = null;
109            }
110            return oldTransport;
111        }
112    }
113
114    /**
115     * Returns true if this observer is interested in notifications for changes
116     * made through the cursor the observer is registered with.
117     */
118    public boolean deliverSelfNotifications() {
119        return false;
120    }
121
122    /**
123     * This method is called when a change occurs to the cursor that
124     * is being observed.
125     *
126     * @param selfChange true if the update was caused by a call to <code>commit</code> on the
127     *  cursor that is being observed.
128     */
129    public void onChange(boolean selfChange) {}
130
131    public final void dispatchChange(boolean selfChange) {
132        if (mHandler == null) {
133            onChange(selfChange);
134        } else {
135            mHandler.post(new NotificationRunnable(selfChange));
136        }
137    }
138}
139