-
-
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.