-1

두 개의 로더가 있는데 각각 다른 컨테이너에서 데이터를로드합니다.로더가 데이터 또는 빈 커서를 반환하지 않습니다.

프래그먼트는 첫 번째 컨텐츠 제공자의 약품 ID와 함께 제공되며 첫 번째 로더는 해당 약과 관련된 모든 정보를로드합니다. 제 2 로더는 제 2 콘텐츠 제공자에게 그 약물과 관련된 모든 경보를 질의하기로되어있다.

첫 번째 로더는 정상적으로 작동하고 올바른 데이터를 모두 반환합니다. 그러나 두 번째 로더는 테이블에 충분한 관련 데이터가 있다는 사실을 알고 있지만 null 커서를 반환합니다. 두 번째 로더에 대한 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"); 
     } 
    } 
} 

}

+0

AlarmProvider 클래스를 게시 할 수 있습니까? – hieuxit

+0

매니페스트에 올바르게 등록되었습니다. 방금 확인 했어. – Feingat35

답변

4

오, 알았어. 알았어. 을 query 알람 프로 바이더 클래스에서 돌려 받는다. :)). 이것에 대한 커서를 반환합시다

+0

... 오 와우. 나는 내 자신의 무능함에 솔직히 깜짝 놀랐다. 정말 고맙습니다. 지금은 잘 작동합니다. :) – Feingat35

1

onLoadFinished() 방법은 당신에게 null 커서를 통과하면, 그는 ContentProviderquery() 방법은 null를 반환했습니다 것을 의미한다. 이 경우 null을 반환하지 않도록 query() 메서드를 수정해야합니다.

+0

null이 반환되는 이유를 알고 있습니까? 이 코드는 비슷한 환경에서 null이 아닌 커서를 반환하는 첫 번째 컨텐츠 공급자의 코드와 거의 동일하므로 여기서 내가 다르게하고있는 것이 확실하지 않습니다. – Feingat35