-
-
Save peterkuterna/3144266 to your computer and use it in GitHub Desktop.
| package com.example; | |
| import android.content.Context; | |
| import android.database.Cursor; | |
| import android.support.v4.app.Fragment; | |
| import android.support.v4.app.FragmentManager; | |
| import android.support.v4.app.FragmentPagerAdapter; | |
| import android.util.SparseIntArray; | |
| import android.view.ViewGroup; | |
| import java.util.HashMap; | |
| public abstract class CursorFragmentPagerAdapter extends FragmentPagerAdapter { | |
| protected boolean mDataValid; | |
| protected Cursor mCursor; | |
| protected Context mContext; | |
| protected SparseIntArray mItemPositions; | |
| protected HashMap<Object, Integer> mObjectMap; | |
| protected int mRowIDColumn; | |
| public CursorFragmentPagerAdapter(Context context, FragmentManager fm, Cursor cursor) { | |
| super(fm); | |
| init(context, cursor); | |
| } | |
| void init(Context context, Cursor c) { | |
| mObjectMap = new HashMap<Object, Integer>(); | |
| boolean cursorPresent = c != null; | |
| mCursor = c; | |
| mDataValid = cursorPresent; | |
| mContext = context; | |
| mRowIDColumn = cursorPresent ? c.getColumnIndexOrThrow("_id") : -1; | |
| } | |
| public Cursor getCursor() { | |
| return mCursor; | |
| } | |
| @Override | |
| public int getItemPosition(Object object) { | |
| Integer rowId = mObjectMap.get(object); | |
| if (rowId != null && mItemPositions != null) { | |
| return mItemPositions.get(rowId, POSITION_NONE); | |
| } | |
| return POSITION_NONE; | |
| } | |
| public void setItemPositions() { | |
| mItemPositions = null; | |
| if (mDataValid) { | |
| int count = mCursor.getCount(); | |
| mItemPositions = new SparseIntArray(count); | |
| mCursor.moveToPosition(-1); | |
| while (mCursor.moveToNext()) { | |
| int rowId = mCursor.getInt(mRowIDColumn); | |
| int cursorPos = mCursor.getPosition(); | |
| mItemPositions.append(rowId, cursorPos); | |
| } | |
| } | |
| } | |
| @Override | |
| public Fragment getItem(int position) { | |
| if (mDataValid) { | |
| mCursor.moveToPosition(position); | |
| return getItem(mContext, mCursor); | |
| } else { | |
| return null; | |
| } | |
| } | |
| @Override | |
| public void destroyItem(ViewGroup container, int position, Object object) { | |
| mObjectMap.remove(object); | |
| super.destroyItem(container, position, object); | |
| } | |
| @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); | |
| } | |
| int rowId = mCursor.getInt(mRowIDColumn); | |
| Object obj = super.instantiateItem(container, position); | |
| mObjectMap.put(obj, Integer.valueOf(rowId)); | |
| return obj; | |
| } | |
| public abstract Fragment getItem(Context context, Cursor cursor); | |
| @Override | |
| public int getCount() { | |
| if (mDataValid) { | |
| return mCursor.getCount(); | |
| } else { | |
| return 0; | |
| } | |
| } | |
| 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; | |
| mCursor = newCursor; | |
| if (newCursor != null) { | |
| mRowIDColumn = newCursor.getColumnIndexOrThrow("_id"); | |
| mDataValid = true; | |
| } else { | |
| mRowIDColumn = -1; | |
| mDataValid = false; | |
| } | |
| setItemPositions(); | |
| notifyDataSetChanged(); | |
| return oldCursor; | |
| } | |
| @Override | |
| public long getItemId(int position) { | |
| if (!mDataValid || !mCursor.moveToPosition(position)) { | |
| return super.getItemId(position); | |
| } | |
| int rowId = mCursor.getInt(mRowIDColumn); | |
| return rowId; | |
| } | |
| } |
We fixed it with:
public Cursor swapCursor(Cursor newCursor) {
if (newCursor == mCursor) {
return null;
}
Cursor oldCursor = mCursor;
mCursor = newCursor;
if (newCursor != null) {
mRowIDColumn = newCursor.getColumnIndexOrThrow(BaseColumns._ID);
mDataValid = true;
notifyDataSetChanged();
} else {
mRowIDColumn = -1;
mDataValid = false;
}
setItemPositions();
return oldCursor;
}Moving the notifyDataSetChanged into the if-statement better mimics the CursorAdapter-behaviour also.
Hey. Thanks for this @peterkuterna
I had some issues with data not updating on calling swapCursor - changed as follows:
public Cursor swapCursor(Cursor newCursor) {
if (newCursor == mCursor) {
return null;
}
Cursor oldCursor = mCursor;
mCursor = newCursor;
if (newCursor != null) {
mRowIDColumn = newCursor.getColumnIndexOrThrow("_id");
mDataValid = true;
} else {
mRowIDColumn = -1;
mDataValid = false;
}
setItemPositions();
if (mDataValid){
notifyDataSetChanged();
}
return oldCursor;
}
...if it helps anyone. Seems to work for me,
I forked this gist , with above change and subclassing of FragmentStatePagerAdapter rather than FragmentPagerAdapter - just removed getItemId(int pos) Seem to work well. https://gist.github.com/aegis1980/95b757047749ae19c484
Thank you. It works fine.
P.S: Android is so feeble so we forced to reinvent the wheel for every 5 minites. And What is reason to believe it so great? I'm developing android apps for 4th year and I use third hand's codes everywhere and every case. Is that so?
Please how do i use this in my code
There is a IllegalStateException that is thrown when trying to destroy the Activity because swapCursor is generally called with a null cursor to remove any of the previous cursor references.