コンテンツプロバイダーとDBで使用するローダーマネージャーを実装しようとすると、エラーが発生します。
logcatの出力から始めましょう:
1-19 16:37:33.628: I/(20193): Loaded EGL implementation /system/lib//egl/libEGL_tegra_impl
01-19 16:37:33.648: I/(20193): Loading GLESv2 implementation /system/lib//egl/libGLESv2_tegra_impl
01-19 16:37:33.883: E/CursorWindow(20193): Failed to read row 0, column -1 from a CursorWindow which has 11 rows, 1 columns.
01-19 16:37:33.883: W/dalvikvm(20193): threadid=1: thread exiting with uncaught exception (group=0x40cfc2d0)
01-19 16:37:33.893: E/AndroidRuntime(20193): FATAL EXCEPTION: main
01-19 16:37:33.893: E/AndroidRuntime(20193): java.lang.IllegalStateException: Couldn't read row 0, col -1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.database.CursorWindow.nativeGetString(Native Method)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.database.CursorWindow.getString(CursorWindow.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at adapters.FastScrollAdapter.getView(FastScrollAdapter.java:99)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.widget.AbsListView.obtainView(AbsListView.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.widget.ListView.makeAndAddView(ListView.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.widget.ListView.fillDown(ListView.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.widget.ListView.fillFromTop(ListView.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.widget.ListView.layoutChildren(ListView.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.widget.AbsListView.onLayout(AbsListView.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.view.View.layout(View.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.view.ViewGroup.layout(ViewGroup.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.widget.LinearLayout.setChildFrame(LinearLayout.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.widget.LinearLayout.layoutVertical(LinearLayout.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.widget.LinearLayout.onLayout(LinearLayout.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.view.View.layout(View.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.view.ViewGroup.layout(ViewGroup.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.widget.LinearLayout.setChildFrame(LinearLayout.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.widget.LinearLayout.layoutVertical(LinearLayout.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.widget.LinearLayout.onLayout(LinearLayout.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.view.View.layout(View.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.view.ViewGroup.layout(ViewGroup.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.widget.FrameLayout.onLayout(FrameLayout.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.view.View.layout(View.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.view.ViewGroup.layout(ViewGroup.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.support.v4.view.ViewPager.onLayout(ViewPager.java:1520)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.view.View.layout(View.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.view.ViewGroup.layout(ViewGroup.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.widget.LinearLayout.setChildFrame(LinearLayout.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.widget.LinearLayout.layoutVertical(LinearLayout.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.widget.LinearLayout.onLayout(LinearLayout.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.view.View.layout(View.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.view.ViewGroup.layout(ViewGroup.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.widget.FrameLayout.onLayout(FrameLayout.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.view.View.layout(View.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.view.ViewGroup.layout(ViewGroup.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.widget.LinearLayout.setChildFrame(LinearLayout.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.widget.LinearLayout.layoutVertical(LinearLayout.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.widget.LinearLayout.onLayout(LinearLayout.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.view.View.layout(View.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.view.ViewGroup.layout(ViewGroup.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.widget.FrameLayout.onLayout(FrameLayout.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.view.View.layout(View.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.view.ViewGroup.layout(ViewGroup.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.view.ViewRootImpl.performLayout(ViewRootImpl.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.view.Choreographer$CallbackRecord.run(Choreographer.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.view.Choreographer.doCallbacks(Choreographer.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.view.Choreographer.doFrame(Choreographer.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.os.Handler.handleCallback(Handler.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.os.Handler.dispatchMessage(Handler.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.os.Looper.loop(Looper.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at android.app.ActivityThread.main(ActivityThread.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at java.lang.reflect.Method.invokeNative(Native Method)
01-19 16:37:33.893: E/AndroidRuntime(20193): at java.lang.reflect.Method.invoke(Method.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java)
01-19 16:37:33.893: E/AndroidRuntime(20193): at dalvik.system.NativeStart.main(Native Method)
リストを表示するフラグメントは次のとおりです。
public class ShiftsFragment extends Fragment implements
LoaderManager.LoaderCallbacks<Cursor> {
public static Typeface tf, tf2, roboto;
private FastScrollAdapter adapter;
ListView ls;
public static ShiftsFragment newInstance(String title) {
ShiftsFragment pageFragment = new ShiftsFragment();
return pageFragment;
}
@SuppressLint("NewApi")
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.shifts, container, false);
/*
* StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
* .detectAll().penaltyLog().build()); StrictMode.setVmPolicy(new
* StrictMode.VmPolicy.Builder()
* .detectLeakedSqlLiteObjects().detectLeakedClosableObjects()
* .penaltyLog().penaltyDeath().build());
*/
roboto = Typeface.createFromAsset(getActivity().getAssets(),
"fonts/JuraLight.ttf");
tf = Typeface.createFromAsset(getActivity().getAssets(),
"fonts/Advert.ttf");
tf2 = Typeface.createFromAsset(getActivity().getAssets(),
"fonts/passion.ttf");
TextView SF = (TextView) view.findViewById(R.id.total);
SF.setTypeface(tf);
ls = (ListView)view.findViewById(android.R.id.list);
getLoaderManager().initLoader(0, null, this);
return view;
}
public Loader<Cursor> onCreateLoader(int loaderId, Bundle args) {
// Query the db asyncronously
String[] projection = { DBAdapter.KEY_ROWID,
DBAdapter.KEY_TIMESTAMP_IN, DBAdapter.KEY_TIMESTAMP_OUT };
String where = null;
String[] whereArgs = null;
String sortOrder = null;
CursorLoader cursorLoader = new CursorLoader(getActivity(),
provider.CONTENT_URI, projection, null, null, null);
return cursorLoader;
}
@SuppressLint("NewApi")
@Override
public void onLoadFinished(Loader<Cursor> arg0, Cursor arg1) {
// Update adapter and views // must use a handler to sync UI thread
// stuff
adapter = new FastScrollAdapter(getActivity(), arg1);
ls.setAdapter(adapter);
}
@Override
public void onLoaderReset(Loader<Cursor> arg0) {
// release references
}
}
これは私のコンテンツプロバイダークラスです:
public class provider extends ContentProvider {
private DBAdapter dbAdapter;
private static final String AUTHORITY = "provider";
private static final String BASE_PATH = "todos";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY
+ "/" + BASE_PATH);
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// TODO Auto-generated method stub
return 0;
}
@Override
public String getType(Uri uri) {
// TODO Auto-generated method stub
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean onCreate() {
dbAdapter = new DBAdapter(getContext());
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
DBAdapter dba = new DBAdapter(getContext());
dba.open();
SQLiteDatabase db = DBAdapter.db;
queryBuilder.setTables(DBAdapter.DATABASE_TABLE);
Cursor cursor = queryBuilder.query(db, projection, selection,
selectionArgs, null, null, sortOrder);
cursor.setNotificationUri(getContext().getContentResolver(), uri);
// TODO Auto-generated method stub
return cursor;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
// TODO Auto-generated method stub
return 0;
}
}
これが私自身のカスタムアダプタです:
// This is a custom adapter that will use cursor to get data from SQLite DB as the source.
public class FastScrollAdapter extends CursorAdapter {
private LayoutInflater mInflater;
public static Cursor cursor;
public static int c = 0;
public static ViewHolder holder;
public DBAdapter dba;
Context context;
public FastScrollAdapter(Context context, Cursor c) {
super(context, c);
this.mInflater = LayoutInflater.from(context);
this.cursor = c;
this.context = context;
}
public FastScrollAdapter(Context context, Cursor c, boolean autoRequery) {
super(context, c, autoRequery);
this.mInflater = LayoutInflater.from(context);
this.cursor = c;
}
// Here we shall look to see if the View already exists and create a new one
// if not.
@Override
public View getView(int position, View convertView, ViewGroup parent) {
dba = new DBAdapter(context);
this.cursor = dba.getAllShifts();
int listLength = cursor.getCount();
// If view doesn't exists = create a new one and also store it (all of
// the views) in our ViewHolder class called "holder"
if (convertView == null) {
convertView = this.mInflater.inflate(R.layout.list_entry2, null);
holder = new ViewHolder();
holder.TL = (TableLayout) convertView.findViewById(R.id.TableBG);
holder.info = (TextView) convertView.findViewById(R.id.Info);
holder.info.setTypeface(SettingsFragment.roboto);
holder.info.setText("Info");
holder.dateDisp = (TextView) convertView
.findViewById(R.id.dateDisp);
holder.timeInShift = (TextView) convertView
.findViewById(R.id.timeInShift);
holder.day = (TextView) convertView.findViewById(R.id.day);
holder.Money = (TextView) convertView.findViewById(R.id.Money);
holder.shiftDisp = (TextView) convertView
.findViewById(R.id.shiftDisp);
holder.start_finish = (TextView) convertView
.findViewById(R.id.start_finish);
holder.Duration = (TextView) convertView
.findViewById(R.id.Duration);
holder.insert = (TextView) convertView.findViewById(R.id.insert);
holder.insert.setTypeface(ShiftsFragment.roboto);
convertView.setTag(holder);
// If exists, just fetch this view and display it.
} else {
holder = (ViewHolder) convertView.getTag();
}
this.cursor.moveToPosition(position);
// Set some values...
/*************** Taken From DB ******************/
holder.start_finish.setText(this.cursor.getString(this.cursor
.getColumnIndex(DBAdapter.KEY_START_TEXT_VIEW))
+ this.cursor.getString(this.cursor
.getColumnIndex(DBAdapter.KEY_END_TEXT_VIEW)));
holder.start_finish.setTypeface(ShiftsFragment.roboto);
holder.shiftDisp.setText(this.cursor.getString(this.cursor
.getColumnIndex(DBAdapter.KEY_MONEY)));
holder.shiftDisp.setTypeface(ShiftsFragment.roboto);
//
holder.dateDisp.setText(this.cursor.getString(this.cursor
.getColumnIndex(DBAdapter.KEY_DATE)));
holder.dateDisp.setTypeface(ShiftsFragment.roboto);
holder.day.setText(this.cursor.getString(this.cursor
.getColumnIndex(DBAdapter.KEY_DAY)));
holder.day.setTypeface(ShiftsFragment.roboto);
holder.timeInShift.setText(this.cursor.getString(this.cursor
.getColumnIndex(DBAdapter.KEY_TOTAL_TIME_OF_SHIFT_STRING)));
holder.timeInShift.setTypeface(ShiftsFragment.roboto);
holder.insert.setText(this.cursor.getString(this.cursor
.getColumnIndex(DBAdapter.KEY_INSERT_MODE)));
//
/*************** Regular ones ******************/
holder.info.setTypeface(ShiftsFragment.roboto);
holder.info.setText("Date:");
holder.Money.setTypeface(ShiftsFragment.roboto);
holder.Money.setText("Money Made:");
holder.Duration.setTypeface(ShiftsFragment.roboto);
holder.Duration.setText("Duration:");
return convertView;
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return null;
}
static class ViewHolder {
TextView info;
TextView dateDisp;
TextView day;
TextView Duration;
TextView start_finish;
TextView Money;
TextView shiftDisp;
TextView timeInShift;
TextView insert;
TableLayout TL;
}
public static void animate(final View v) {
final Animation out = new AlphaAnimation(1, 0);
out.setInterpolator(new DecelerateInterpolator());
out.setDuration(350);
v.setAnimation(out);
out.start();
out.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
Log.i("Animation", "Started");
}
@Override
public void onAnimationRepeat(Animation animation) {
// Shifts.setSummaryCursor.requery();
}
@Override
public void onAnimationEnd(Animation animation) {
// Shifts.setSummaryCursor.requery();
}
});
}
}