Home | History | Annotate | Download | only in database
      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 
     17 package android.database;
     18 
     19 import android.net.Uri;
     20 import 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  */
     26 public 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