-1

2 つのローダーがあり、それぞれが異なるコンテンツ プロバイダーからデータをロードします。

フラグメントには、最初のコンテンツ プロバイダーから医薬品の ID が提供され、最初のローダーがその医薬品に関連するすべての情報を読み込みます。2 番目のローダーは、2 番目のコンテンツ プロバイダーに、その薬に関連するすべてのアラームを照会することになっています。

最初のローダーは問題なく動作し、正しいデータをすべて返します。ただし、2 番目のローダーは null カーソルを返すように見えますが、関連するはずのテーブルに大量のデータがあることはわかっています。2 番目のローダーの onLoadFinished のデータで getCount() を使用するとアプリがクラッシュするため、「表示される」と言います。これが発生すると考えられる唯一の理由は、カーソルが null の場合です。

とにかく、これが私のローダーのコードです。必要に応じて、必要な他のコードを提供できます。

/**
 * 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");
        }
    }
}

}

4

2 に答える 2

4

ああ、ああ、私nullはあなたqueryが AlarmProvider クラスのメソッドに戻っていることを発見しました :))。これにカーソルを戻しましょう

于 2013-08-24T03:54:14.943 に答える