Back to project page CircularView.
The source code is released under:
Apache License
If you think the Android project CircularView listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
package com.sababado.circularview; // www .j a v a 2 s . c om import android.database.ContentObserver; import android.database.Cursor; import android.database.DataSetObservable; import android.database.DataSetObserver; import android.os.Handler; import android.util.Log; import android.widget.CursorAdapter; /** * Adapter that exposes data from a {@link android.database.Cursor Cursor} to a * {@link android.widget.ListView ListView} widget. * <p/> * The Cursor must include a column named "_id" or this class will not work. * Additionally, using {@link android.database.MergeCursor} with this class will * not work if the merged Cursors have overlapping values in their "_id" * columns. */ public abstract class CircularViewCursorAdapter implements BaseCircularViewAdapter { private static final String TAG = CircularViewCursorAdapter.class.getSimpleName(); private final DataSetObservable mDataSetObservable = new DataSetObservable(); protected boolean mDataValid; protected boolean mAutoRequery; private Cursor mCursor; protected int mRowIDColumn; protected ChangeObserver mChangeObserver; protected DataSetObserver mDataSetObserver; /** * Constructor that always enables auto-requery. * * @param c The cursor from which to get the data. * @deprecated This option is discouraged, as it results in Cursor queries * being performed on the application's UI thread and thus can cause poor * responsiveness or even Application Not Responding errors. As an alternative, * use {@link android.app.LoaderManager} with a {@link android.content.CursorLoader}. */ @Deprecated public CircularViewCursorAdapter(Cursor c) { init(c, CursorAdapter.FLAG_AUTO_REQUERY); } /** * Constructor that allows control over auto-requery. It is recommended * you not use this, but instead {@link #CircularViewCursorAdapter(Cursor, int)}. * When using this constructor, {@link android.widget.CursorAdapter#FLAG_REGISTER_CONTENT_OBSERVER} * will always be set. * * @param c The cursor from which to get the data. * @param autoRequery If true the adapter will call requery() on the * cursor whenever it changes so the most recent * data is always displayed. Using true here is discouraged. */ public CircularViewCursorAdapter(Cursor c, boolean autoRequery) { init(c, autoRequery ? CursorAdapter.FLAG_AUTO_REQUERY : CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER); } /** * Recommended constructor. * * @param c The cursor from which to get the data. * @param flags Flags used to determine the behavior of the adapter; may * be any combination of {@link android.widget.CursorAdapter#FLAG_AUTO_REQUERY} and * {@link android.widget.CursorAdapter#FLAG_REGISTER_CONTENT_OBSERVER}. */ public CircularViewCursorAdapter(Cursor c, int flags) { init(c, flags); } void init(final Cursor c, int flags) { if ((flags & CursorAdapter.FLAG_AUTO_REQUERY) == CursorAdapter.FLAG_AUTO_REQUERY) { flags |= CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER; mAutoRequery = true; } else { mAutoRequery = false; } boolean cursorPresent = c != null; mCursor = c; mDataValid = cursorPresent; mRowIDColumn = cursorPresent ? c.getColumnIndexOrThrow("_id") : -1; if ((flags & CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER) == CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER) { mChangeObserver = new ChangeObserver(); mDataSetObserver = new MyDataSetObserver(); } else { mChangeObserver = null; mDataSetObserver = null; } if (cursorPresent) { if (mChangeObserver != null) c.registerContentObserver(mChangeObserver); if (mDataSetObserver != null) c.registerDataSetObserver(mDataSetObserver); } } public void registerDataSetObserver(DataSetObserver observer) { mDataSetObservable.registerObserver(observer); } public void unregisterDataSetObserver(DataSetObserver observer) { mDataSetObservable.unregisterObserver(observer); } /** * Notifies the attached observers that the underlying data has been changed * and any View reflecting the data set should refresh itself. */ public void notifyDataSetChanged() { mDataSetObservable.notifyChanged(); } /** * Notifies the attached observers that the underlying data is no longer valid * or available. Once invoked this adapter is no longer valid and should * not report further data set changes. */ public void notifyDataSetInvalidated() { mDataSetObservable.notifyInvalidated(); } /** * Returns the cursor. * * @return the cursor. */ public Cursor getCursor() { return mCursor; } @Override public int getCount() { if (mDataValid && mCursor != null) { return mCursor.getCount(); } else { return 0; } } @Override public void setupMarker(int position, Marker marker) { setupMarker(position, marker, mCursor); } /** * Setup the marker that should show at a given position. The position will be between 0 and the value returned by {@link #getCount()}. * * @param position Position of the marker to show. * @param marker The marker that will be used to display. * @param cursor Cursor that is being used. */ public abstract void setupMarker(int position, Marker marker, Cursor cursor); /** * Returns a cursor pointed to the given position. * * @param position position to set on the cursor. * @return a cursor set to the position. */ public Cursor getItem(int position) { if (mDataValid && mCursor != null) { mCursor.moveToPosition(position); return mCursor; } else { return null; } } /** * Swap in a new Cursor, returning the old Cursor. Unlike * {@link #changeCursor(Cursor)}, the returned old Cursor is <em>not</em> * closed. * * @param newCursor The new cursor to be used. * @return Returns the previously set Cursor, or null if there was not one. * If the given new Cursor is the same instance is the previously set * Cursor, null is also returned. */ public Cursor swapCursor(Cursor newCursor) { if (newCursor == mCursor) { return null; } Cursor oldCursor = mCursor; if (oldCursor != null) { if (mChangeObserver != null) oldCursor.unregisterContentObserver(mChangeObserver); if (mDataSetObserver != null) oldCursor.unregisterDataSetObserver(mDataSetObserver); } mCursor = newCursor; if (newCursor != null) { if (mChangeObserver != null) newCursor.registerContentObserver(mChangeObserver); if (mDataSetObserver != null) newCursor.registerDataSetObserver(mDataSetObserver); mRowIDColumn = newCursor.getColumnIndexOrThrow("_id"); mDataValid = true; // notify the observers about the new cursor notifyDataSetChanged(); } else { mRowIDColumn = -1; mDataValid = false; // notify the observers about the lack of a data set notifyDataSetInvalidated(); } return oldCursor; } /** * Change the underlying cursor to a new cursor. If there is an existing cursor it will be * closed. * * @param cursor The new cursor to be used */ public void changeCursor(Cursor cursor) { Cursor old = swapCursor(cursor); if (old != null) { old.close(); } } /** * Called when the {@link ContentObserver} on the cursor receives a change notification. * The default implementation provides the auto-requery logic, but may be overridden by * sub classes. * * @see ContentObserver#onChange(boolean) */ protected void onContentChanged() { if (mAutoRequery && mCursor != null && !mCursor.isClosed()) { mDataValid = mCursor.requery(); } } private class ChangeObserver extends ContentObserver { public ChangeObserver() { super(new Handler()); } @Override public boolean deliverSelfNotifications() { return true; } @Override public void onChange(boolean selfChange) { onContentChanged(); } } private class MyDataSetObserver extends DataSetObserver { @Override public void onChanged() { mDataValid = true; notifyDataSetChanged(); } @Override public void onInvalidated() { mDataValid = false; notifyDataSetInvalidated(); } } }