/* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.database; import android.os.Handler; /** * Receives call backs for changes to content. * Must be implemented by objects which are added to a {@link ContentObservable}. */ public abstract class ContentObserver { private final Object mLock = new Object(); private Transport mTransport; // guarded by mLock Handler mHandler; /** * Creates a content observer. * * @param handler The handler to run {@link #onChange} on, or null if none. */ public ContentObserver(Handler handler) { mHandler = handler; } /** * Gets access to the binder transport object. Not for public consumption. * * {@hide} */ public IContentObserver getContentObserver() { synchronized (mLock) { if (mTransport == null) { mTransport = new Transport(this); } return mTransport; } } /** * Gets access to the binder transport object, and unlinks the transport object * from the ContentObserver. Not for public consumption. * * {@hide} */ public IContentObserver releaseContentObserver() { synchronized (mLock) { final Transport oldTransport = mTransport; if (oldTransport != null) { oldTransport.releaseContentObserver(); mTransport = null; } return oldTransport; } } /** * Returns true if this observer is interested receiving self-change notifications. * * Subclasses should override this method to indicate whether the observer * is interested in receiving notifications for changes that it made to the * content itself. * * @return True if self-change notifications should be delivered to the observer. */ public boolean deliverSelfNotifications() { return false; } /** * This method is called when a content change occurs. * * @param selfChange True if this is a self-change notification. */ public void onChange(boolean selfChange) { // Do nothing. Subclass should override. } /** * Dispatches a change notification to the observer. * * If a {@link Handler} was supplied to the {@link ContentObserver} constructor, * then a call to the {@link #onChange} method is posted to the handler's message queue. * Otherwise, the {@link #onChange} method is invoked immediately on this thread. * * @param selfChange True if this is a self-change notification. */ public final void dispatchChange(boolean selfChange) { if (mHandler == null) { onChange(selfChange); } else { mHandler.post(new NotificationRunnable(selfChange)); } } private final class NotificationRunnable implements Runnable { private final boolean mSelf; public NotificationRunnable(boolean self) { mSelf = self; } @Override public void run() { ContentObserver.this.onChange(mSelf); } } private static final class Transport extends IContentObserver.Stub { private ContentObserver mContentObserver; public Transport(ContentObserver contentObserver) { mContentObserver = contentObserver; } @Override public void onChange(boolean selfChange) { ContentObserver contentObserver = mContentObserver; if (contentObserver != null) { contentObserver.dispatchChange(selfChange); } } public void releaseContentObserver() { mContentObserver = null; } } }