Created
March 24, 2015 02:35
-
-
Save boxme/c2878219dd5f01279425 to your computer and use it in GitHub Desktop.
PagerAdapter that uses uses Cursor as its data format
This file contains 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 characters
public abstract class CursorPagerAdapter extends PagerAdapter { | |
public static final String TAG = CursorPagerAdapter.class.getSimpleName(); | |
protected WeakReference<Context> ctxRef; | |
protected boolean mDataValid; | |
protected boolean mAutoRequery; | |
protected Cursor mCursor; | |
protected int mRowIDColumn; | |
protected ChangeObserver mChangeObserver; | |
protected DataSetObserver mDataSetObserver; | |
/** | |
* If set the adapter will call requery() on the cursor whenever a content change notification is | |
* delivered. Implies {@link #FLAG_REGISTER_CONTENT_OBSERVER}. | |
* | |
* @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 static final int FLAG_AUTO_REQUERY = 0x01; | |
/** | |
* If set the adapter will register a content observer on the cursor and will call {@link | |
* # onContentChanged()} when a notification comes in. Be careful when using this flag: you will | |
* need to unset the current Cursor from the adapter to avoid leaks due to its registered | |
* observers. This flag is not needed when using a CursorAdapter with a {@link | |
* android.content.CursorLoader}. | |
*/ | |
public static final int FLAG_REGISTER_CONTENT_OBSERVER = 0x02; | |
public CursorPagerAdapter(Context context, Cursor c, int flags) { | |
init(context, c, flags); | |
} | |
void init(Context context, Cursor c, int flags) { | |
if ((flags & FLAG_AUTO_REQUERY) == FLAG_AUTO_REQUERY) { | |
flags |= FLAG_REGISTER_CONTENT_OBSERVER; | |
mAutoRequery = true; | |
} else { | |
mAutoRequery = false; | |
} | |
boolean cursorPresent = c != null; | |
mCursor = c; | |
mDataValid = cursorPresent; | |
ctxRef = new WeakReference<>(context); | |
mRowIDColumn = cursorPresent ? c.getColumnIndexOrThrow("_id") : -1; | |
if ((flags & FLAG_REGISTER_CONTENT_OBSERVER) == 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 Cursor getCursor() { | |
return mCursor; | |
} | |
@Override | |
public int getCount() { | |
if (mDataValid && mCursor != null) | |
return mCursor.getCount(); | |
else | |
return 0; | |
} | |
@Override | |
public Object instantiateItem(ViewGroup container, int position) { | |
if (!mDataValid) { | |
throw new IllegalStateException("this should only be called when the cursor is valid"); | |
} | |
if (!mCursor.moveToPosition(position)) { | |
throw new IllegalStateException("couldn't move cursor to position " + position); | |
} | |
Context context = ctxRef.get(); | |
if (context != null) { | |
View v = newView(context, mCursor, (ViewGroup) container); | |
bindView(v, context, mCursor); | |
((ViewPager) container).addView(v); | |
return v; | |
} else { | |
throw new IllegalStateException("context is null"); | |
} | |
} | |
@Override | |
public void destroyItem(ViewGroup container, int position, Object object) { | |
((ViewPager) container).removeView((View) object); | |
} | |
@Override | |
public int getItemPosition(Object object) { | |
return POSITION_NONE; | |
} | |
@Override | |
public boolean isViewFromObject(View view, Object o) { | |
return view == o; | |
} | |
public abstract View newView(Context context, Cursor cursor, ViewGroup parent); | |
public abstract void bindView(View view, Context context, Cursor cursor); | |
public void changeCursor(Cursor cursor) { | |
Cursor old = swapCursor(cursor); | |
if (old != null) { | |
old.close(); | |
} | |
} | |
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; | |
notifyDataSetChanged(); | |
} | |
return oldCursor; | |
} | |
private void onContentChange() { | |
if (mAutoRequery && mCursor != null && !mCursor.isClosed()) { | |
mDataValid = mCursor.requery(); | |
} | |
} | |
private class ChangeObserver extends ContentObserver { | |
public ChangeObserver() { | |
super(new Handler()); | |
} | |
/** | |
* | |
* @return True if self-change notifications should be delivered to the observer. | |
*/ | |
@Override | |
public boolean deliverSelfNotifications() { | |
return true; | |
} | |
/** | |
* This method is called when a content change occurs. | |
* @param selfChange | |
*/ | |
@Override | |
public void onChange(boolean selfChange) { | |
onContentChange(); | |
} | |
} | |
private class MyDataSetObserver extends DataSetObserver { | |
@Override | |
public void onChanged() { | |
mDataValid = true; | |
notifyDataSetChanged(); | |
} | |
@Override | |
public void onInvalidated() { | |
mDataValid = false; | |
notifyDataSetChanged(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment