我有两个加载器,每个加载器从不同的内容提供者加载数据。
该片段由第一个内容提供者提供的药物 ID 提供,第一个加载程序加载与该药物相关的所有信息。第二个加载程序应该向第二个内容提供者查询与该药物相关的所有警报。
第一个加载器工作得很好,并返回所有正确的数据。然而,第二个加载器似乎返回了一个空游标,尽管我知道表中有大量数据应该是相关的。我说“出现”是因为对第二个加载器的 onLoadFinished 中的数据使用 getCount() 会导致我的应用程序崩溃,而我认为会发生这种情况的唯一原因是光标为空。
无论如何,这是我的装载机的代码。如果你需要,我可以给你任何你想要的代码。
/**
* Initializes the loaders.
*/
@Override
public Loader<Cursor> onCreateLoader(int loaderId, Bundle bundle) {
CursorLoader loader = null;
long id = getArguments().getLong(ARG_MED_ID);
switch(loaderId) {
case 0: // MedList Loader
Log.d("MedManager", "Loading med data");
Uri singleUri = ContentUris.withAppendedId(MedProvider.CONTENT_URI, id);
String[] projection = { MedTable.MED_ID,
MedTable.MED_NAME,
MedTable.MED_DOSAGE,
MedTable.MED_DATE_FILLED,
MedTable.MED_DURATION };
loader = new CursorLoader(getActivity(), singleUri,
projection, null, null,
MedTable.MED_NAME + " COLLATE LOCALIZED ASC");
break;
case 1: // AlarmList Loader
Log.d("MedManager", "Theoretically loading alarm list");
Uri baseUri = AlarmProvider.CONTENT_URI;
// Create and return a CursorLoader that will take care of
// creating a Cursor for the data being displayed.
String[] alarmProjection = { DailyAlarmTable.ALARM_ID,
DailyAlarmTable.ALARM_MEDNUM,
DailyAlarmTable.ALARM_TIME };
String select = "((" + DailyAlarmTable.ALARM_MEDNUM + " NOTNULL) AND ("
+ DailyAlarmTable.ALARM_MEDNUM + " = " + id + "))";
loader = new CursorLoader(getActivity(), baseUri,
alarmProjection, select, null,
DailyAlarmTable.ALARM_TIMESTAMP + " ASC");
break;
}
return loader;
}
/**
* Customizes the various TextViews in the layout to match
* the values pulled from the MedTable, or swaps the alarm cursor
* into the adapter.
*/
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
switch(loader.getId()) {
case 0:
setUpMedDetails(data);
break;
case 1:
Log.d("MedManager", "Alarm finished loading");
/*
* these lines are commented out because their presence causes
* the app to crash.
*/
/*
boolean isEmpty = data.getCount() < 1;
if(isEmpty) {
Log.d("MedManager", "No results");
}
*/
mAdapter.swapCursor(data);
break;
}
}
@Override
public void onLoaderReset(Loader<Cursor> arg0) {
// TODO Auto-generated method stub
if(arg0.getId() == 1) {
mAdapter.swapCursor(null);
}
}
编辑:为了完整起见,并且因为总是存在我只是一个大白痴忽略一些明显的东西的可能性,这是我在表格中添加警报的代码:
/**
* This function will turn the hour and day into an "HH:mm AM/PM" string,
* calculate the timestamp, and then inserts them into the table.
*/
@Override
public void onTimePicked(int hourOfDay, int minute) {
Log.d("MedManager", "onTimePicked triggered");
// Convert the hour and minute into a string
String alarmString = formatAlarmString(hourOfDay, minute);
// Convert the hour and minute into a timestamp
long alarmTimestamp = getAlarmTimestamp(hourOfDay, minute);
// Define the URI to receive the results of the insertion
Uri newUri = null;
// Define a contentValues object to contain the new Values
ContentValues mValues = new ContentValues();
// Add medId;
long medId = getIntent().getLongExtra(MedDetailFragment.ARG_MED_ID, 0);
mValues.put(DailyAlarmTable.ALARM_MEDNUM, medId);
// Add the timestamp
mValues.put(DailyAlarmTable.ALARM_TIMESTAMP, alarmTimestamp);
// Add the time string
mValues.put(DailyAlarmTable.ALARM_TIME, alarmString);
// Insert the new alarm
Toast.makeText(getApplicationContext(), "medNum = " + medId, Toast.LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(), "time = " + alarmString, Toast.LENGTH_SHORT).show();
newUri = getContentResolver().insert(AlarmProvider.CONTENT_URI, mValues);
String uriStr = newUri.toString();
Toast.makeText(getApplicationContext(), "Uri = " + uriStr, Toast.LENGTH_SHORT).show();
}
根据要求,这是我的 AlarmProvider 类。
package com.gmail.jfeingold35.medicationmanager.alarmprovider;
import java.util.Arrays;
import java.util.HashSet;
import com.gmail.jfeingold35.medicationmanager.database.AlarmDatabaseHelper;
import com.gmail.jfeingold35.medicationmanager.database.DailyAlarmTable;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
public class AlarmProvider extends ContentProvider {
// Database
private AlarmDatabaseHelper database;
// Used for the UriMatcher
private static final int ALARMS = 10;
private static final int ALARM_ID = 20;
private static final String AUTHORITY = "com.gmail.jfeingold35.medicationmanager.alarmprovider";
private static final String BASE_PATH = "medicationmanager";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY
+ "/" + BASE_PATH);
public static final String CONTENT_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE
+ "/alarms";
public static final String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE
+ "/alarm";
private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static {
sUriMatcher.addURI(AUTHORITY, BASE_PATH, ALARMS);
sUriMatcher.addURI(AUTHORITY, BASE_PATH + "/#", ALARM_ID);
}
@Override
public boolean onCreate() {
database = new AlarmDatabaseHelper(getContext());
return false;
}
/**
* Perform a query from the alarm database
*/
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// Using SQLiteQueryBuilder instead of the query() method
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
// Check if the caller requested a column which doesn't exist
checkColumns(projection);
// Set the table
queryBuilder.setTables(DailyAlarmTable.TABLE_ALARM);
int uriType = sUriMatcher.match(uri);
switch(uriType) {
case ALARMS:
break;
case ALARM_ID:
// Adding the ID to the original query
queryBuilder.appendWhere(DailyAlarmTable.ALARM_ID + "="
+ uri.getLastPathSegment());
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
SQLiteDatabase db = database.getWritableDatabase();
Cursor cursor = queryBuilder.query(db, projection, selection,
selectionArgs, null, null, sortOrder);
// Make sure that potential listeners are getting notified
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return null;
}
/**
* Delete from the alarm database
*/
public int delete(Uri uri, String selection, String[] selectionArgs) {
int uriType = sUriMatcher.match(uri);
SQLiteDatabase db = database.getWritableDatabase();
int rowsDeleted = 0;
switch(uriType) {
case ALARMS:
rowsDeleted = db.delete(DailyAlarmTable.TABLE_ALARM, selection,
selectionArgs);
break;
case ALARM_ID:
String id = uri.getLastPathSegment();
if(TextUtils.isEmpty(selection)) {
rowsDeleted = db.delete(DailyAlarmTable.TABLE_ALARM,
DailyAlarmTable.ALARM_ID + "=" + id, null);
} else {
rowsDeleted = db.delete(DailyAlarmTable.TABLE_ALARM,
DailyAlarmTable.ALARM_ID + "=" + id + " and " + selection,
selectionArgs);
}
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return rowsDeleted;
}
@Override
public String getType(Uri uri) {
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
int uriType = sUriMatcher.match(uri);
SQLiteDatabase db = database.getWritableDatabase();
long id = 0;
switch(uriType) {
case ALARMS:
id = db.insert(DailyAlarmTable.TABLE_ALARM, null, values);
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return Uri.parse(BASE_PATH + "/" + id);
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
int uriType = sUriMatcher.match(uri);
SQLiteDatabase db = database.getWritableDatabase();
int rowsUpdated = 0;
switch(uriType) {
case ALARMS:
rowsUpdated = db.update(DailyAlarmTable.TABLE_ALARM,
values,
selection,
selectionArgs);
break;
case ALARM_ID:
String id = uri.getLastPathSegment();
if(TextUtils.isEmpty(selection)) {
rowsUpdated = db.update(DailyAlarmTable.TABLE_ALARM,
values,
DailyAlarmTable.ALARM_ID + "=" + id,
null);
} else {
rowsUpdated = db.update(DailyAlarmTable.TABLE_ALARM,
values,
DailyAlarmTable.ALARM_ID + "=" + id + " and " + selection,
selectionArgs);
}
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return rowsUpdated;
}
/**
* Confirms that the columns the user requested exist.
* @param projection
*/
public void checkColumns(String[] projection) {
String[] available = { DailyAlarmTable.ALARM_ID,
DailyAlarmTable.ALARM_MEDNUM,
DailyAlarmTable.ALARM_TIMESTAMP,
DailyAlarmTable.ALARM_TIME };
if(projection != null) {
HashSet<String> requestedColumns = new HashSet<String>(Arrays.asList(projection));
HashSet<String> availableColumns = new HashSet<String>(Arrays.asList(available));
// Check if all columns which are requested are available
if(!availableColumns.containsAll(requestedColumns)) {
throw new IllegalArgumentException("Unknown columsn in projection");
}
}
}
}