加载程序不返回任何数据,或空光标 [英] Loader returns no data, or an empty cursor

查看:76
本文介绍了加载程序不返回任何数据,或空光标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个加载程序,每个加载程序都从不同的内容提供程序加载数据.

I've got two loaders, each of which loads data from a different content provider.

从第一内容提供商处向片段提供药物的ID,并且第一加载程序加载与该药物有关的所有信息.第二个加载器应该向第二个内容提供者查询与该药物相关的所有警报.

The fragment is supplied with the ID of a medication from the first content provider, and the first loader loads all of the information related to that medication. The second loader is supposed to query the second content provider for all of the alarms associated with that medication.

第一个加载器工作正常,并返回所有正确的数据.但是,第二个加载器似乎返回一个空游标,即使我知道一个事实,即表中有很多数据应该是相关的.我之所以说出现",是因为对第二个加载器的onLoadFinished中的数据使用getCount()会导致我的应用崩溃,而我能想到的唯一原因就是游标为null.

The first loader works just fine, and returns all of the correct data. However, the second loader appears to return a null cursor, even though I know for a fact that there is plenty of data in the table that should be relevant. I say "appears" because using getCount() on the data in in onLoadFinished for the second loader causes my app to crash, and the only reason I can think that this would occur is if the cursor were null.

无论如何,这是我的装载机的代码.如果需要,我可以为您提供其他所需的代码.

Anyway, here's the code for my loaders. If you need, I can give you the code for anything else you want.

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

为了完整起见,并且由于总是存在着我只是一个巨大的白痴,可以忽略明显的东西的可能性,所以这里是我将警报添加到表中的代码:

For completeness' sake, and because the possibility always exists that I'm simply a massive idiot overlooking something obvious, here's the code by which I add alarms into the table:

/**
 * 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类.

As requested, here's my AlarmProvider class.

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

}

推荐答案

哦,好吧,我发现您在AlarmProvider类的 query 方法中返回了 null :)).让我们为此返回光标

Oh oh, okay I found that you return null in your query method of AlarmProvider class :)). Let's return cursor for this

这篇关于加载程序不返回任何数据,或空光标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆