我遵循了一些教程,这些教程解释了如何将 CursorLoader 与 SQLiteDatabase 一起使用。当我运行我的 ListView 时,没有返回任何结果。我已经确认数据库中有一个使用 Eclipse 插件的条目。
这是我的带有 sqliteopenhelper 实现的 contentprovider
public class DiaryDataProvider extends ContentProvider {
public static final String DATABASE_NAME = "data.db";
public static final int DATABASE_VERSION = 1;
// implementation of SQLiteOpenHelper
private static class DiaryDbHelper extends SQLiteOpenHelper {
// creating and deleting the database and table
private static final String TEXT_TYPE = " TEXT";
private static final String REAL_TYPE = " REAL";
private static final String INTEGER_TYPE = " INTEGER";
private static final String COMMA_SEP = ",";
private static final String SQL_CREATE_ENTRIES = "CREATE TABLE "
+ DiarySchema.TABLE_NAME + " (" + DiarySchema._ID
+ " INTEGER PRIMARY KEY," + DiarySchema.COLUMN_NAME_DIARY_ID
+ TEXT_TYPE + COMMA_SEP + DiarySchema.COLUMN_NAME_DATE
+ TEXT_TYPE + COMMA_SEP + DiarySchema.COLUMN_NAME_TIME
+ TEXT_TYPE + COMMA_SEP + DiarySchema.COLUMN_NAME_SEVERITY
+ TEXT_TYPE + COMMA_SEP + DiarySchema.COLUMN_NAME_LOCATION_LAT
+ REAL_TYPE + COMMA_SEP + DiarySchema.COLUMN_NAME_LOCATION_LONG
+ REAL_TYPE + COMMA_SEP
+ DiarySchema.COLUMN_NAME_LOCATION_DETAIL + TEXT_TYPE
+ COMMA_SEP + DiarySchema.COLUMN_NAME_HAS_FOOD + INTEGER_TYPE
+ COMMA_SEP + DiarySchema.COLUMN_NAME_DETAILS + TEXT_TYPE
+ " )";
public DiaryDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(SQL_CREATE_ENTRIES);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + DiarySchema.TABLE_NAME);
onCreate(db);
}
}
private DiaryDbHelper dbHelper;
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
SQLiteDatabase db = dbHelper.getReadableDatabase();
final int match = DiarySchema.URI_MATCHER.match(uri);
switch (match) {
// retrieve diary list
case DiarySchema.PATH_TOKEN: {
SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
builder.setTables(DiarySchema.TABLE_NAME);
return db.delete(DiarySchema.TABLE_NAME, selection, selectionArgs);
}
default:
return 0;
}
}
@Override
public String getType(Uri uri) {
final int match = DiarySchema.URI_MATCHER.match(uri);
switch (match) {
case DiarySchema.PATH_TOKEN:
return DiarySchema.CONTENT_TYPE_DIR;
case DiarySchema.PATH_FOR_ID_TOKEN:
return DiarySchema.CONTENT_ITEM_TYPE;
default:
throw new UnsupportedOperationException("URI " + uri
+ " is not supported.");
}
}
@Override
public Uri insert(Uri uri, ContentValues values) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
int token = DiarySchema.URI_MATCHER.match(uri);
switch (token) {
case DiarySchema.PATH_TOKEN: {
long id = db.insert(DiarySchema.TABLE_NAME, null, values);
getContext().getContentResolver().notifyChange(uri, null);
return DiarySchema.CONTENT_URI.buildUpon()
.appendPath(String.valueOf(id)).build();
}
default: {
throw new UnsupportedOperationException("URI: " + uri
+ " not supported.");
}
}
}
@Override
public boolean onCreate() {
dbHelper = new DiaryDbHelper(getContext());
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteDatabase db = dbHelper.getReadableDatabase();
final int match = DiarySchema.URI_MATCHER.match(uri);
switch (match) {
// retrieve diary list
case DiarySchema.PATH_TOKEN: {
SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
builder.setTables(DiarySchema.TABLE_NAME);
return builder.query(db, projection, selection, null, null, sortOrder, null);
}
default:
return null;
}
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
SQLiteDatabase db = dbHelper.getReadableDatabase();
final int match = DiarySchema.URI_MATCHER.match(uri);
switch (match) {
// retrieve diary list
case DiarySchema.PATH_TOKEN: {
SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
builder.setTables(DiarySchema.TABLE_NAME);
return db.update(DiarySchema.TABLE_NAME, values, selection,
selectionArgs);
}
default:
return 0;
}
}
}
这是随之而来的架构
public abstract class DiarySchema implements BaseColumns {
public static final String TABLE_NAME = "diary";
public static final String COLUMN_NAME_DIARY_ID = "diaryid";
public static final String COLUMN_NAME_DATE = "date";
public static final String COLUMN_NAME_TIME = "time";
public static final String COLUMN_NAME_SEVERITY = "severity";
public static final String COLUMN_NAME_LOCATION_LAT = "locationlat";
public static final String COLUMN_NAME_LOCATION_LONG = "locationlong";
public static final String COLUMN_NAME_LOCATION_DETAIL = "locationdetail";
public static final String COLUMN_NAME_DETAILS = "details";
public static final String COLUMN_NAME_HAS_FOOD = "hasfood";
public static final String PATH = "diaries";
public static final int PATH_TOKEN = 100;
public static final String PATH_FOR_ID = "diaries/#";
public static final int PATH_FOR_ID_TOKEN = 200;
public static final String CONTENT_TYPE_DIR = ContentResolver.CURSOR_DIR_BASE_TYPE + "/diaries";
public static final String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/diaries";
public static final String AUTHORITY = "com.foo.bar.contentproviders";
private static final Uri BASE_URI = Uri.parse("content://" + AUTHORITY);
public static final UriMatcher URI_MATCHER = buildUriMatcher();
public static final Uri CONTENT_URI = BASE_URI.buildUpon().appendPath(PATH)
.build();
private static UriMatcher buildUriMatcher() {
final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
final String authority = AUTHORITY;
matcher.addURI(authority, PATH, PATH_TOKEN);
matcher.addURI(authority, PATH_FOR_ID, PATH_FOR_ID_TOKEN);
return matcher;
}
// Prevent anyone from instantiating this class
private DiarySchema() {
};
}
我的 ContentProvider 在 androidmanifest.xml 文件中声明为...
<provider
android:name="com.foo.bar.contentproviders.DiaryDataProvider"
android:authorities="com.foo.bar.contentproviders"
android:exported="false" />
我的 ListFragment 看起来像......
public class FragDiaryEntries extends SherlockListFragment implements
LoaderManager.LoaderCallbacks<Cursor> {
private static final int URL_LOADER = 0;
private View view;
private Map<Integer, DiaryHolder> diaryHolders = new HashMap<Integer, DiaryHolder>();
CustomAdapter adapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.frag_diary_entries, container);
// start the cursor loader getting data to populate diary view
getLoaderManager().initLoader(URL_LOADER, null, this);
// Set up adapter
adapter = new CustomAdapter(getActivity().getApplicationContext(), null);
setListAdapter(adapter);
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO different indicator of no data yet
((TextView) getListView().getEmptyView()).setText("It's Empty");
super.onActivityCreated(savedInstanceState);
}
/* Loader callback implemented methods */
@Override
public Loader<Cursor> onCreateLoader(int loaderId, Bundle bundle) {
Loader<Cursor> cursorLoader = null;
// Get all of the diary entries
switch (loaderId) {
case URL_LOADER:
String[] projection = { DiarySchema._ID,
DiarySchema.COLUMN_NAME_DATE, DiarySchema.COLUMN_NAME_TIME,
DiarySchema.COLUMN_NAME_SEVERITY,
DiarySchema.COLUMN_NAME_LOCATION_LAT,
DiarySchema.COLUMN_NAME_LOCATION_LONG,
DiarySchema.COLUMN_NAME_LOCATION_DETAIL,
DiarySchema.COLUMN_NAME_DETAILS,
DiarySchema.COLUMN_NAME_HAS_FOOD };
cursorLoader = new CursorLoader(getActivity(),
DiarySchema.CONTENT_URI, projection, null, null, null);
}
return cursorLoader;
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
adapter.swapCursor(cursor);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
adapter.swapCursor(null);
}
// Custom CursorAdapter
private class CustomAdapter extends CursorAdapter {
private Cursor cursor;
public CustomAdapter(Context context, Cursor c) {
super(context, c, 0);
this.cursor = c;
}
@Override
public int getCount() {
return cursor == null ? 0 : cursor.getCount();
}
@Override
public Cursor getCursor() {
return super.getCursor();
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
int position = cursor.getPosition();
// Map values from cursor to fields
TextView created = (TextView) view.findViewById(R.id.diary_created);
TextView severity = (TextView) view
.findViewById(R.id.diary_severity);
TextView location = (TextView) view
.findViewById(R.id.diary_location);
CheckBox checkbox = (CheckBox) view
.findViewById(R.id.diary_item_checked);
// Create a holder object to store some row details
if (!diaryHolders.containsKey(position)) {
// Put the cursor in the correct position
cursor.moveToPosition(position);
String date = cursor.getString(cursor
.getColumnIndexOrThrow(DiarySchema.COLUMN_NAME_DATE));
String time = cursor.getString(cursor
.getColumnIndexOrThrow(DiarySchema.COLUMN_NAME_TIME));
created.setText(date + " at " + time);
String sev = cursor
.getString(cursor
.getColumnIndexOrThrow(DiarySchema.COLUMN_NAME_SEVERITY));
severity.setText(sev);
String loc = cursor
.getString(cursor
.getColumnIndexOrThrow(DiarySchema.COLUMN_NAME_LOCATION_DETAIL));
location.setText(loc);
// Other values to put into holder
long latitude = cursor
.getLong(cursor
.getColumnIndexOrThrow(DiarySchema.COLUMN_NAME_LOCATION_LAT));
long longitude = cursor
.getLong(cursor
.getColumnIndexOrThrow(DiarySchema.COLUMN_NAME_LOCATION_LONG));
int hasFood = cursor
.getInt(cursor
.getColumnIndexOrThrow(DiarySchema.COLUMN_NAME_HAS_FOOD));
diaryHolders.put(position,
new DiaryHolder(position, checkbox.isChecked(),
new Diary(date, time, sev, loc, latitude,
longitude, hasFood)));
} else {
// Populate from map
DiaryHolder holder = diaryHolders.get(position);
Diary diary = holder.getDiaryData();
created.setText(diary.getDate().concat(diary.getTime()));
severity.setText(diary.getSeverity());
location.setText(diary.getLocationDetail());
checkbox.setChecked(holder.isSelected());
}
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup container) {
// Inflate a new view
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.diary_list_item, container);
bindView(view, context, cursor);
return view;
}
}
// Holder class for row values
private class DiaryHolder {
private long rowId;
private boolean selected;
private Diary diaryData;
public DiaryHolder(long rowId, boolean selected, Diary diaryData) {
this.rowId = rowId;
this.selected = selected;
this.diaryData = diaryData;
}
public Diary getDiaryData() {
return diaryData;
}
public void setDiaryData(Diary diaryData) {
this.diaryData = diaryData;
}
public long getRowId() {
return rowId;
}
public void setRowId(long rowId) {
this.rowId = rowId;
}
public boolean isSelected() {
return selected;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
}
}
我知道我的 ContentProvider 的插入部分可以工作,因为我能够插入一条记录。我想要做的是我拉回所有数据并将其显示在我的列表视图中。任何帮助,将不胜感激。