Created
August 13, 2014 18:57
Revisions
-
chalup created this gist
Aug 13, 2014 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,204 @@ package com.futuresimple.base.provider; import com.google.common.collect.Iterables; import android.content.ContentResolver; import android.database.ContentObservable; import android.database.ContentObserver; import android.database.Cursor; import android.database.CursorWrapper; import android.net.Uri; import android.os.Build; import java.lang.ref.WeakReference; import java.util.Collections; import java.util.LinkedHashSet; public class MultiUriCursorWrapper extends CursorWrapper { public MultiUriCursorWrapper(Cursor cursor) { super(cursor); } protected boolean mClosed; protected ContentResolver mContentResolver; private final LinkedHashSet<Uri> mNotifyUris = new LinkedHashSet<Uri>(); private final Object mSelfObserverLock = new Object(); private ContentObserver mSelfObserver; private boolean mSelfObserverRegistered; private final LinkedHashSet<Uri> mChangedByUris = new LinkedHashSet<Uri>(); private final ContentObservable mContentObservable = new ContentObservable(); @Override public void deactivate() { onDeactivateOrClose(); super.deactivate(); } protected void onDeactivateOrClose() { if (mSelfObserver != null) { mContentResolver.unregisterContentObserver(mSelfObserver); mSelfObserverRegistered = false; } } @Override public boolean requery() { if (mSelfObserver != null && !mSelfObserverRegistered) { for (Uri notifyUri : mNotifyUris) { mContentResolver.registerContentObserver(notifyUri, true, mSelfObserver); } mSelfObserverRegistered = true; } boolean success = super.requery(); if (success) { mChangedByUris.clear(); } return success; } @Override public boolean isClosed() { return super.isClosed() && mClosed; } @Override public void close() { super.close(); mClosed = true; mContentObservable.unregisterAll(); onDeactivateOrClose(); } @SuppressWarnings("deprecation") @Override public void registerContentObserver(ContentObserver observer) { mContentObservable.registerObserver(observer); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { for (Uri changedByUri : mChangedByUris) { observer.dispatchChange(false, changedByUri); } } else { if (!mChangedByUris.isEmpty()) { observer.dispatchChange(false); } } } @Override public void unregisterContentObserver(ContentObserver observer) { // cursor will unregister all observers when it close if (!mClosed) { mContentObservable.unregisterObserver(observer); } } @SuppressWarnings("deprecation") private void onChange(boolean selfChange, Uri uri) { synchronized (mSelfObserverLock) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { mContentObservable.dispatchChange(selfChange, uri); } else { mContentObservable.dispatchChange(selfChange); } if (selfChange) { for (Uri notifyUri : mNotifyUris) { mContentResolver.notifyChange(notifyUri, mSelfObserver); } } if (!selfChange) { mChangedByUris.add(uri); } } } public MultiUriCursorWrapper withNotificationUris(ContentResolver cr, Iterable<Uri> uris) { synchronized (mSelfObserverLock) { Iterables.addAll(mNotifyUris, uris); mContentResolver = cr; if (mSelfObserver == null) { mSelfObserver = new SelfContentObserver(this); } for (Uri uri : uris) { mContentResolver.registerContentObserver(uri, true, mSelfObserver); } mSelfObserverRegistered = true; } return this; } public MultiUriCursorWrapper withNotificationUri(ContentResolver cr, Uri uri) { return withNotificationUris(cr, Collections.singletonList(uri)); } public LinkedHashSet<Uri> getNotificationUris() { return mNotifyUris; } @Override public void setNotificationUri(ContentResolver cr, Uri notifyUri) { withNotificationUri(cr, notifyUri); } @Override public Uri getNotificationUri() { synchronized (mSelfObserverLock) { return Iterables.getFirst(mNotifyUris, null); } } @Override protected void finalize() { try { super.finalize(); if (mSelfObserver != null && mSelfObserverRegistered) { mContentResolver.unregisterContentObserver(mSelfObserver); } if (!mClosed) close(); } catch (Throwable e) { // ignored } } private static class SelfContentObserver extends ContentObserver { WeakReference<MultiUriCursorWrapper> mCursor; public SelfContentObserver(MultiUriCursorWrapper cursor) { super(null); mCursor = new WeakReference<MultiUriCursorWrapper>(cursor); } @Override public boolean deliverSelfNotifications() { return false; } @Override public void onChange(boolean selfChange, Uri uri) { MultiUriCursorWrapper cursor = mCursor.get(); if (cursor != null) { cursor.onChange(false, uri); } } @Override public void onChange(boolean selfChange) { onChange(selfChange, null); } } }