2017-02-08 2 views
0

У меня есть класс ContentProvider, который используется моими действиями для доступа, записи, запроса и удаления данных из моей локальной базы данных. Я постоянно открываю свою базу данных в рамках методов ContentProvider для доступа к данным. Мой вопрос: где подходящее место для закрытия базы данных в ContentProvider?Управление утечками памяти в ContentProvider

Я попытался сделать это в запросе, вставлять и удалять методы переопределения, но получаю следующее исключение:

Caused by: java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed. 

Вот мой ContentProvider класса следуют моей базы данных Класс:

public class GroceryContentProvider extends ContentProvider { 
final static int FOOD_ITEM = 100; 
final static int FOOD_ITEM_WITH_ID = 101; 
private UriMatcher uriMatcher = buildUriMatcher(); 
private final String TAG = "GROCERY_PROVIDER"; 

public static UriMatcher buildUriMatcher(){ 
    UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 
    uriMatcher.addURI(FoodContract.CONTENT_AUTHORITY,FoodContract.PATH,FOOD_ITEM); 
    uriMatcher.addURI(FoodContract.CONTENT_AUTHORITY,FoodContract.PATH + "/#",FOOD_ITEM_WITH_ID); 
    return uriMatcher; 
} 

@Override 
public boolean onCreate() { 
    return false; 
} 

@Nullable 
@Override 
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { 
    Cursor cursor; 
    FoodDatabase foodDatabase = new FoodDatabase(getContext()); 
    int match = uriMatcher.match(uri); 

    switch (match){ 
     case FOOD_ITEM:{ 
      foodDatabase.openReadableDB(); 
      cursor = foodDatabase.getAllRows(projection,selection,selectionArgs,sortOrder); 

      break; 
     } 
     default: 
      throw new UnsupportedOperationException("Unknown URI: " + uri); 
    } 
    cursor.setNotificationUri(getContext().getContentResolver(),uri); 

    return cursor; 
} 

@Nullable 
@Override 
public String getType(Uri uri) { 
    return null; 
} 

@Nullable 
@Override 
public Uri insert(Uri uri, ContentValues values) { 
    int match = uriMatcher.match(uri); 
    Uri returnUri; 
    switch (match){ 
     case FOOD_ITEM:{ 
      Context context = getContext(); 
      FoodDatabase foodDatabase = new FoodDatabase(context); 
      foodDatabase.openWriteableDB(); 
      long id = foodDatabase.insertRow(values); 
      if(id>0){ 
       returnUri = ContentUris.withAppendedId(FoodContract.FoodList.CONTENT_URI,id); 
      }else{ 
       throw new android.database.SQLException("Failed to insert row into " + uri); 
      } 
      break; 
     } 
     default: 
      throw new UnsupportedOperationException("Unknown URI: " + uri); 
    } 
    getContext().getContentResolver().notifyChange(uri,null); 
    return returnUri; 
} 

@Override 
public int delete(Uri uri, String selection, String[] selectionArgs) { 
    int match = uriMatcher.match(uri); 
    int taskDeleted; 
    switch (match){ 
     case FOOD_ITEM_WITH_ID:{ 
      String idForDeletion = uri.getPathSegments().get(1); 
      FoodDatabase foodDatabase = new FoodDatabase(getContext()); 
      foodDatabase.openWriteableDB(); 
      taskDeleted = foodDatabase.deleteRow(FoodContract.FoodList.TABLE_NAME,"_id=?",new String[]{idForDeletion}); 
      break; 
     } 
     default: 
      throw new UnsupportedOperationException("URI UNKNOWN " + uri); 
    } 
    if(taskDeleted!=0){ 
     getContext().getContentResolver().notifyChange(uri,null); 
    } 

    return taskDeleted; 
} 

@Override 
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 
    return 0; 
}} 

базы данных :

public class FoodDatabase { 
private SQLiteDatabase db; 
private DatabaseHelper databaseHelper; 
private Context context; 
public static final int DB_VERSION = 1; 
public static final String DB_NAME = "food_list_db"; 

private final String CREATE_DATABASE = "CREATE TABLE " + FoodContract.FoodList.TABLE_NAME + " (" 
     + FoodContract.FoodList._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " 
     + FoodContract.FoodList.ITEM_NAME + " TEXT NOT NULL" 
     + ");"; 


public FoodDatabase(Context context){ 
    this.context = context; 
    databaseHelper = new DatabaseHelper(context); 
} 

public FoodDatabase openWriteableDB(){ 
    db = databaseHelper.getWritableDatabase(); 
    return this; 
} 

public FoodDatabase openReadableDB(){ 
    db = databaseHelper.getReadableDatabase(); 
    return this; 
} 

public long insertRow(ContentValues cv){ 
    return db.insert(FoodContract.FoodList.TABLE_NAME,null,cv); 
} 

public Cursor getAllRows(String[] projection, String selection, String[] selectionArgs, String sortOrder){ 
    return db.query(FoodContract.FoodList.TABLE_NAME,projection,selection,selectionArgs,null,null,sortOrder); 
} 

public int deleteRow(String table, String whereClause, String[]whereArgs){ 
    return db.delete(table,whereClause,whereArgs); 
} 

public void closeDB(){ 
    db.close(); 
} 

private class DatabaseHelper extends SQLiteOpenHelper { 
    public DatabaseHelper(Context context) { 
     super(context, DB_NAME, null, DB_VERSION); 
    } 

    @Override 
    public void onCreate(SQLiteDatabase db) { 
     db.execSQL(CREATE_DATABASE); 

    } 

    @Override 
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
     db.execSQL("DROP TABLE IF EXISTS " + FoodContract.FoodList.TABLE_NAME); 
     onCreate(db); 
    } 
}} 
+0

https://groups.google.com/forum/#!msg/android-developers/NwDRpHUXt0U/jIam4Q8-cqQJ – pskink

ответ

2

Предлагаю вам изменить onCreate метод поставщика контента инициализацией FoodDatabase класса в переменном-члене mFoodDatabase:

@Override 
public boolean onCreate() { 
    mFoodDatabase = new FoodDatabase(getContext()); 
    return true; 
} 

И, внутри ваших методов контента поставщика (запрос, вставка, обновление и удаление), вместо того, чтобы повторно инстанцировании FoodDatabase объекта, попробуйте использовать тот, который хранится в переменной-члене mFoodDatabase.

Надежда может помочь

Смежные вопросы