1 package com.android.launcher3.util; 2 3 import android.content.ContentValues; 4 import android.content.Context; 5 import android.database.Cursor; 6 import android.database.sqlite.SQLiteDatabase; 7 import android.database.sqlite.SQLiteException; 8 import android.database.sqlite.SQLiteFullException; 9 import android.database.sqlite.SQLiteOpenHelper; 10 import android.util.Log; 11 12 /** 13 * An extension of {@link SQLiteOpenHelper} with utility methods for a single table cache DB. 14 * Any exception during write operations are ignored, and any version change causes a DB reset. 15 */ 16 public abstract class SQLiteCacheHelper { 17 private static final String TAG = "SQLiteCacheHelper"; 18 19 private static final boolean IN_MEMORY_CACHE = false; 20 21 private final String mTableName; 22 private final MySQLiteOpenHelper mOpenHelper; 23 24 private boolean mIgnoreWrites; 25 SQLiteCacheHelper(Context context, String name, int version, String tableName)26 public SQLiteCacheHelper(Context context, String name, int version, String tableName) { 27 if (IN_MEMORY_CACHE) { 28 name = null; 29 } 30 mTableName = tableName; 31 mOpenHelper = new MySQLiteOpenHelper(context, name, version); 32 33 mIgnoreWrites = false; 34 } 35 36 /** 37 * @see SQLiteDatabase#delete(String, String, String[]) 38 */ delete(String whereClause, String[] whereArgs)39 public void delete(String whereClause, String[] whereArgs) { 40 if (mIgnoreWrites) { 41 return; 42 } 43 try { 44 mOpenHelper.getWritableDatabase().delete(mTableName, whereClause, whereArgs); 45 } catch (SQLiteFullException e) { 46 onDiskFull(e); 47 } catch (SQLiteException e) { 48 Log.d(TAG, "Ignoring sqlite exception", e); 49 } 50 } 51 52 /** 53 * @see SQLiteDatabase#insertWithOnConflict(String, String, ContentValues, int) 54 */ insertOrReplace(ContentValues values)55 public void insertOrReplace(ContentValues values) { 56 if (mIgnoreWrites) { 57 return; 58 } 59 try { 60 mOpenHelper.getWritableDatabase().insertWithOnConflict( 61 mTableName, null, values, SQLiteDatabase.CONFLICT_REPLACE); 62 } catch (SQLiteFullException e) { 63 onDiskFull(e); 64 } catch (SQLiteException e) { 65 Log.d(TAG, "Ignoring sqlite exception", e); 66 } 67 } 68 onDiskFull(SQLiteFullException e)69 private void onDiskFull(SQLiteFullException e) { 70 Log.e(TAG, "Disk full, all write operations will be ignored", e); 71 mIgnoreWrites = true; 72 } 73 74 /** 75 * @see SQLiteDatabase#query(String, String[], String, String[], String, String, String) 76 */ query(String[] columns, String selection, String[] selectionArgs)77 public Cursor query(String[] columns, String selection, String[] selectionArgs) { 78 return mOpenHelper.getReadableDatabase().query( 79 mTableName, columns, selection, selectionArgs, null, null, null); 80 } 81 clear()82 public void clear() { 83 mOpenHelper.clearDB(mOpenHelper.getWritableDatabase()); 84 } 85 close()86 public void close() { 87 mOpenHelper.close(); 88 } 89 onCreateTable(SQLiteDatabase db)90 protected abstract void onCreateTable(SQLiteDatabase db); 91 92 /** 93 * A private inner class to prevent direct DB access. 94 */ 95 private class MySQLiteOpenHelper extends NoLocaleSQLiteHelper { 96 MySQLiteOpenHelper(Context context, String name, int version)97 public MySQLiteOpenHelper(Context context, String name, int version) { 98 super(context, name, version); 99 } 100 101 @Override onCreate(SQLiteDatabase db)102 public void onCreate(SQLiteDatabase db) { 103 onCreateTable(db); 104 } 105 106 @Override onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)107 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 108 if (oldVersion != newVersion) { 109 clearDB(db); 110 } 111 } 112 113 @Override onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion)114 public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { 115 if (oldVersion != newVersion) { 116 clearDB(db); 117 } 118 } 119 clearDB(SQLiteDatabase db)120 private void clearDB(SQLiteDatabase db) { 121 db.execSQL("DROP TABLE IF EXISTS " + mTableName); 122 onCreate(db); 123 } 124 } 125 } 126