3

this example을 기반으로 간단한 테스트 응용 프로그램을 만들었습니다. 데이터베이스와 ListView에 데이터를 삽입하는 단추가 있습니다. 둘 다 MainActivity에 있습니다. 원래 코드에서는 onResume()에서만 호출 된 restartLoader() 이었지만 onResume()이 실행되었을 때만 ListView가 새로 고쳐졌습니다. displayListView() 끝에 restartLoader()을 넣었습니다. 이제는 누름 단추를 누른 후 Listview에 새 행이 표시됩니다. 하지만 그것이 올바른 해결책이라고 생각하지 않습니다.CursorLoader를 사용하여 SQLite의 데이터로 ListView 채우기

public class MainActivity extends FragmentActivity implements LoaderManager.LoaderCallbacks<Cursor>{ 


     private SimpleCursorAdapter dataAdapter; 

     @Override 
     public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     displayListView(); 

     Button add = (Button) findViewById(R.id.add); 
      add.setOnClickListener(new View.OnClickListener() { 

       public void onClick(View v) { 

        ContentValues values = new ContentValues(); 
        values.put(SensorsDb.KEY_TYPE, "wld"); 
        values.put(SensorsDb.KEY_TITLE, "Basement Water Detector"); 
        values.put(SensorsDb.KEY_SERIAL, "33"); 
        values.put(SensorsDb.KEY_VALUE, "NO WATER"); 

        getContentResolver().insert(MyContentProvider.CONTENT_URI,values); 

        displayListView(); 
       } 
       }); 
     } 
     @Override 
     protected void onResume() { 
     super.onResume(); 
     //Starts a new or restarts an existing Loader in this manager 
     getSupportLoaderManager().restartLoader(0, null, MainActivity.this); 
     } 

     private void displayListView() { 
     // The desired columns to be bound 
     String[] columns = new String[] { 
     SensorsDb.KEY_TITLE, 
     SensorsDb.KEY_VALUE 
     }; 
     // the XML defined views which the data will be bound to 
     int[] to = new int[] { 
     R.id.sensorTitle, 
     R.id.sensorState 
     }; 

     // create an adapter from the SimpleCursorAdapter 
     dataAdapter = new SimpleCursorAdapter(this, R.layout.custom_row_view, null, columns, to, 0); 
     //Ensures a loader is initialized and active. 
     getSupportLoaderManager().initLoader(0, null, this); 
     // get reference to the ListView 
     ListView listView = (ListView) findViewById(R.id.sensorList); 
     // Assign adapter to ListView 
     listView.setAdapter(dataAdapter); 

     getSupportLoaderManager().restartLoader(0, null, MainActivity.this); 
     } 

     // This is called when a new Loader needs to be created. 
     @Override 
     public Loader<Cursor> onCreateLoader(int id, Bundle args) { 
     String[] projection = { 
     SensorsDb.KEY_ROWID, 
     SensorsDb.KEY_TYPE, 
     SensorsDb.KEY_TITLE, 
     SensorsDb.KEY_SERIAL, 
     SensorsDb.KEY_VALUE}; 
     CursorLoader cursorLoader = new CursorLoader(this, 
     MyContentProvider.CONTENT_URI, projection, null, null, null); 
     return cursorLoader; 
     } 

     @Override 
     public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 

      dataAdapter.swapCursor(data); 
     } 

     @Override 
     public void onLoaderReset(Loader<Cursor> loader) { 

     dataAdapter.swapCursor(null); 
     } 

     @Override 
     public boolean onCreateOptionsMenu(Menu menu) { 
     getMenuInflater().inflate(R.menu.main, menu); 
     return true; 
     } 
    } 

는 MyContentProvider 클래스에게 있습니다

public class MyContentProvider extends ContentProvider{ 

private MyDatabaseHelper dbHelper; 

private static final int ALL_SENSORS = 1; 
private static final int SINGLE_SENSOR = 2; 

// authority is the symbolic name of your provider 
// To avoid conflicts with other providers, you should use 
// Internet domain ownership (in reverse) as the basis of your provider authority. 
private static final String AUTHORITY = "com.example.contproctest.contentprovider"; 

// create content URIs from the authority by appending path to database table 
public static final Uri CONTENT_URI = 
    Uri.parse("content://" + AUTHORITY + "/sensors"); 

// a content URI pattern matches content URIs using wildcard characters: 
// *: Matches a string of any valid characters of any length. 
    // #: Matches a string of numeric characters of any length. 
private static final UriMatcher uriMatcher; 
static { 
    uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 
    uriMatcher.addURI(AUTHORITY, "sensors", ALL_SENSORS); 
    uriMatcher.addURI(AUTHORITY, "sensors/#", SINGLE_SENSOR); 
} 

// system calls onCreate() when it starts up the provider. 
@Override 
public boolean onCreate() { 
    // get access to the database helper 
    dbHelper = new MyDatabaseHelper(getContext()); 
    return false; 
} 

//Return the MIME type corresponding to a content URI 
@Override 
public String getType(Uri uri) { 

    switch (uriMatcher.match(uri)) { 
    case ALL_SENSORS: 
    return "vnd.android.cursor.dir/vnd.com.example.contproctest.contentprovider.sensors"; 
    case SINGLE_SENSOR: 
    return "vnd.android.cursor.item/vnd.com.example.contproctest.contentprovider.sensors"; 
    default: 
    throw new IllegalArgumentException("Unsupported URI: " + uri); 
    } 
} 

// The insert() method adds a new row to the appropriate table, using the values 
// in the ContentValues argument. If a column name is not in the ContentValues argument, 
// you may want to provide a default value for it either in your provider code or in 
// your database schema. 
@Override 
public Uri insert(Uri uri, ContentValues values) { 

    SQLiteDatabase db = dbHelper.getWritableDatabase(); 
    switch (uriMatcher.match(uri)) { 
    case ALL_SENSORS: 
    //do nothing 
    break; 
    default: 
    throw new IllegalArgumentException("Unsupported URI: " + uri); 
    } 
    long id = db.insert(SensorsDb.SQLITE_TABLE, null, values); 
    getContext().getContentResolver().notifyChange(uri, null); 
    return Uri.parse(CONTENT_URI + "/" + id); 
} 

// The query() method must return a Cursor object, or if it fails, 
// throw an Exception. If you are using an SQLite database as your data storage, 
// you can simply return the Cursor returned by one of the query() methods of the 
// SQLiteDatabase class. If the query does not match any rows, you should return a 
// Cursor instance whose getCount() method returns 0. You should return null only 
// if an internal error occurred during the query process. 
@Override 
public Cursor query(Uri uri, String[] projection, String selection, 
    String[] selectionArgs, String sortOrder) { 

    SQLiteDatabase db = dbHelper.getWritableDatabase(); 
    SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); 
    queryBuilder.setTables(SensorsDb.SQLITE_TABLE); 

    switch (uriMatcher.match(uri)) { 
    case ALL_SENSORS: 
    //do nothing 
    break; 
    case SINGLE_SENSOR: 
    String id = uri.getPathSegments().get(1); 
    queryBuilder.appendWhere(SensorsDb.KEY_ROWID + "=" + id); 
    break; 
    default: 
    throw new IllegalArgumentException("Unsupported URI: " + uri); 
    } 

    Cursor cursor = queryBuilder.query(db, projection, selection, 
    selectionArgs, null, null, sortOrder); 
    return cursor; 

} 

// The delete() method deletes rows based on the seletion or if an id is 
// provided then it deleted a single row. The methods returns the numbers 
// of records delete from the database. If you choose not to delete the data 
// physically then just update a flag here. 
@Override 
public int delete(Uri uri, String selection, String[] selectionArgs) { 

    SQLiteDatabase db = dbHelper.getWritableDatabase(); 
    switch (uriMatcher.match(uri)) { 
    case ALL_SENSORS: 
    //do nothing 
    break; 
    case SINGLE_SENSOR: 
    String id = uri.getPathSegments().get(1); 
    selection = SensorsDb.KEY_ROWID + "=" + id 
    + (!TextUtils.isEmpty(selection) ? 
    " AND (" + selection + ')' : ""); 
    break; 
    default: 
    throw new IllegalArgumentException("Unsupported URI: " + uri); 
    } 
    int deleteCount = db.delete(SensorsDb.SQLITE_TABLE, selection, selectionArgs); 
    getContext().getContentResolver().notifyChange(uri, null); 
    return deleteCount; 
} 

// The update method() is same as delete() which updates multiple rows 
// based on the selection or a single row if the row id is provided. The 
// update method returns the number of updated rows. 
@Override 
public int update(Uri uri, ContentValues values, String selection, 
    String[] selectionArgs) { 
    SQLiteDatabase db = dbHelper.getWritableDatabase(); 
    switch (uriMatcher.match(uri)) { 
    case ALL_SENSORS: 
    //do nothing 
    break; 
    case SINGLE_SENSOR: 
    String id = uri.getPathSegments().get(1); 
    selection = SensorsDb.KEY_ROWID + "=" + id 
    + (!TextUtils.isEmpty(selection) ? 
    " AND (" + selection + ')' : ""); 
    break; 
    default: 
    throw new IllegalArgumentException("Unsupported URI: " + uri); 
    } 
    int updateCount = db.update(SensorsDb.SQLITE_TABLE, values, selection, selectionArgs); 
    getContext().getContentResolver().notifyChange(uri, null); 
    return updateCount; 
} 

} 

답변

0

당신은 CursorLoader이 데이터를들을 수 있기 때문에 CP의 삽입 새로운 데이터 후 restartLoader를 호출의 변화가있을 때 자동으로 업데이트 할 필요가 없습니다 데이터 소스 (ContentProvider) cursor.setNotificationUri()으로 전화를 걸어 CP에있는 쿼리 방법에서 Cursor을 반환하십시오.

@Override 
public Cursor query(Uri uri, String[] projection, String selection, 
String[] selectionArgs, String sortOrder) { 

    SQLiteDatabase db = dbHelper.getWritableDatabase(); 
    SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); 
    queryBuilder.setTables(SensorsDb.SQLITE_TABLE); 

    switch (uriMatcher.match(uri)) { 
    case ALL_SENSORS: 
    //do nothing 
    break; 
    case SINGLE_SENSOR: 
    String id = uri.getPathSegments().get(1); 
    queryBuilder.appendWhere(SensorsDb.KEY_ROWID + "=" + id); 
    break; 
    default: 
    throw new IllegalArgumentException("Unsupported URI: " + uri); 
    } 

    Cursor cursor = queryBuilder.query(db, projection, selection, 
    selectionArgs, null, null, sortOrder); 

    cursor.setNotificationUri(getContext().getContentResolver(), uri); 

    return cursor; 
} 
+0

내 대답은 해결책을 줄 수 있습니까? http://stackoverflow.com/questions/20419278/uri-for-external-database-in-cursorloader –

관련 문제