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.net.Uri; 20import android.os.Handler; 21 22/** 23 * Receives call backs for changes to content. 24 * Must be implemented by objects which are added to a {@link ContentObservable}. 25 */ 26public abstract class ContentObserver { 27 private final Object mLock = new Object(); 28 private Transport mTransport; // guarded by mLock 29 30 Handler mHandler; 31 32 /** 33 * Creates a content observer. 34 * 35 * @param handler The handler to run {@link #onChange} on, or null if none. 36 */ 37 public ContentObserver(Handler handler) { 38 mHandler = handler; 39 } 40 41 /** 42 * Gets access to the binder transport object. Not for public consumption. 43 * 44 * {@hide} 45 */ 46 public IContentObserver getContentObserver() { 47 synchronized (mLock) { 48 if (mTransport == null) { 49 mTransport = new Transport(this); 50 } 51 return mTransport; 52 } 53 } 54 55 /** 56 * Gets access to the binder transport object, and unlinks the transport object 57 * from the ContentObserver. Not for public consumption. 58 * 59 * {@hide} 60 */ 61 public IContentObserver releaseContentObserver() { 62 synchronized (mLock) { 63 final Transport oldTransport = mTransport; 64 if (oldTransport != null) { 65 oldTransport.releaseContentObserver(); 66 mTransport = null; 67 } 68 return oldTransport; 69 } 70 } 71 72 /** 73 * Returns true if this observer is interested receiving self-change notifications. 74 * 75 * Subclasses should override this method to indicate whether the observer 76 * is interested in receiving notifications for changes that it made to the 77 * content itself. 78 * 79 * @return True if self-change notifications should be delivered to the observer. 80 */ 81 public boolean deliverSelfNotifications() { 82 return false; 83 } 84 85 /** 86 * This method is called when a content change occurs. 87 * <p> 88 * Subclasses should override this method to handle content changes. 89 * </p> 90 * 91 * @param selfChange True if this is a self-change notification. 92 */ 93 public void onChange(boolean selfChange) { 94 // Do nothing. Subclass should override. 95 } 96 97 /** 98 * This method is called when a content change occurs. 99 * Includes the changed content Uri when available. 100 * <p> 101 * Subclasses should override this method to handle content changes. 102 * To ensure correct operation on older versions of the framework that 103 * did not provide a Uri argument, applications should also implement 104 * the {@link #onChange(boolean)} overload of this method whenever they 105 * implement the {@link #onChange(boolean, Uri)} overload. 106 * </p><p> 107 * Example implementation: 108 * <pre><code> 109 * // Implement the onChange(boolean) method to delegate the change notification to 110 * // the onChange(boolean, Uri) method to ensure correct operation on older versions 111 * // of the framework that did not have the onChange(boolean, Uri) method. 112 * {@literal @Override} 113 * public void onChange(boolean selfChange) { 114 * onChange(selfChange, null); 115 * } 116 * 117 * // Implement the onChange(boolean, Uri) method to take advantage of the new Uri argument. 118 * {@literal @Override} 119 * public void onChange(boolean selfChange, Uri uri) { 120 * // Handle change. 121 * } 122 * </code></pre> 123 * </p> 124 * 125 * @param selfChange True if this is a self-change notification. 126 * @param uri The Uri of the changed content, or null if unknown. 127 */ 128 public void onChange(boolean selfChange, Uri uri) { 129 onChange(selfChange); 130 } 131 132 /** 133 * Dispatches a change notification to the observer. 134 * <p> 135 * If a {@link Handler} was supplied to the {@link ContentObserver} constructor, 136 * then a call to the {@link #onChange} method is posted to the handler's message queue. 137 * Otherwise, the {@link #onChange} method is invoked immediately on this thread. 138 * </p> 139 * 140 * @param selfChange True if this is a self-change notification. 141 * 142 * @deprecated Use {@link #dispatchChange(boolean, Uri)} instead. 143 */ 144 @Deprecated 145 public final void dispatchChange(boolean selfChange) { 146 dispatchChange(selfChange, null); 147 } 148 149 /** 150 * Dispatches a change notification to the observer. 151 * Includes the changed content Uri when available. 152 * <p> 153 * If a {@link Handler} was supplied to the {@link ContentObserver} constructor, 154 * then a call to the {@link #onChange} method is posted to the handler's message queue. 155 * Otherwise, the {@link #onChange} method is invoked immediately on this thread. 156 * </p> 157 * 158 * @param selfChange True if this is a self-change notification. 159 * @param uri The Uri of the changed content, or null if unknown. 160 */ 161 public final void dispatchChange(boolean selfChange, Uri uri) { 162 if (mHandler == null) { 163 onChange(selfChange, uri); 164 } else { 165 mHandler.post(new NotificationRunnable(selfChange, uri)); 166 } 167 } 168 169 private final class NotificationRunnable implements Runnable { 170 private final boolean mSelfChange; 171 private final Uri mUri; 172 173 public NotificationRunnable(boolean selfChange, Uri uri) { 174 mSelfChange = selfChange; 175 mUri = uri; 176 } 177 178 @Override 179 public void run() { 180 ContentObserver.this.onChange(mSelfChange, mUri); 181 } 182 } 183 184 private static final class Transport extends IContentObserver.Stub { 185 private ContentObserver mContentObserver; 186 187 public Transport(ContentObserver contentObserver) { 188 mContentObserver = contentObserver; 189 } 190 191 @Override 192 public void onChange(boolean selfChange, Uri uri) { 193 ContentObserver contentObserver = mContentObserver; 194 if (contentObserver != null) { 195 contentObserver.dispatchChange(selfChange, uri); 196 } 197 } 198 199 public void releaseContentObserver() { 200 mContentObserver = null; 201 } 202 } 203} 204