如何将一个长的单个 SQLiteOpenHelper 拆分为多个类,每个表一个类
Posted
技术标签:
【中文标题】如何将一个长的单个 SQLiteOpenHelper 拆分为多个类,每个表一个类【英文标题】:How can I split a long, single SQLiteOpenHelper into several classes, one for each table 【发布时间】:2014-10-22 08:49:31 【问题描述】:我知道这已经被问过几次了,但在所有这些问题中,OP 和回答的人都没有提供明确的例子。
所以我想在这里问的是是否有这样的课程
public class MyDatabaseDB
// database constants
public static final String DB_NAME = "mydatabase.db";
public static final int DB_VERSION = 1;
// list table constants
public static final String LIST_TABLE = "list";
public static final String LIST_ID = "_id";
public static final int LIST_ID_COL = 0;
public static final String LIST_NAME = "list_name";
public static final int LIST_NAME_COL = 1;
// task table constants
public static final String TASK_TABLE = "task";
public static final String TASK_ID = "_id";
public static final int TASK_ID_COL = 0;
public static final String TASK_LIST_ID = "list_id";
public static final int TASK_LIST_ID_COL = 1;
public static final String TASK_NAME = "task_name";
public static final int TASK_NAME_COL = 2;
// CREATE and DROP TABLE statements
public static final String CREATE_LIST_TABLE =
"CREATE TABLE " + LIST_TABLE + " (" +
LIST_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
LIST_NAME + " TEXT UNIQUE)";
public static final String CREATE_TASK_TABLE =
"CREATE TABLE " + TASK_TABLE + " (" +
TASK_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
TASK_LIST_ID + " INTEGER, " +
TASK_NAME + " TEXT " +
)";
public static final String DROP_LIST_TABLE =
"DROP TABLE IF EXISTS " + LIST_TABLE;
public static final String DROP_TASK_TABLE =
"DROP TABLE IF EXISTS " + TASK_TABLE;
private static class DBHelper extends SQLiteOpenHelper
public DBHelper(Context context, String name,
CursorFactory factory, int version)
super(context, name, factory, version);
@Override
public void onCreate(SQLiteDatabase db)
// create tables
db.execSQL(CREATE_LIST_TABLE);
db.execSQL(CREATE_TASK_TABLE);
// insert lists
db.execSQL("INSERT INTO list VALUES (1, 'Hobbies')");
db.execSQL("INSERT INTO list VALUES (2, 'Sports')");
// insert sample tasks
db.execSQL("INSERT INTO task VALUES (1, 1, 'Play the guitar')");
db.execSQL("INSERT INTO task VALUES (2, 1, 'Play video games')");
@Override
public void onUpgrade(SQLiteDatabase db,
int oldVersion, int newVersion)
Log.d("Task list", "Upgrading db from version "
+ oldVersion + " to " + newVersion);
db.execSQL(MyDatabaseDB.DROP_LIST_TABLE);
db.execSQL(MyDatabaseDB.DROP_TASK_TABLE);
onCreate(db);
// database object and database helper object
private SQLiteDatabase db;
private DBHelper dbHelper;
// constructor
public MyDatabaseDB(Context context)
dbHelper = new DBHelper(context, DB_NAME, null, DB_VERSION);
// private methods
private void openReadableDB()
db = dbHelper.getReadableDatabase();
private void openWriteableDB()
db = dbHelper.getWritableDatabase();
private void closeDB()
if (db != null)
db.close();
// public methods
public long insertTask(Task task)
ContentValues cv = new ContentValues();
cv.put(TASK_LIST_ID, task.getListId());
cv.put(TASK_NAME, task.getName());
this.openWriteableDB();
long rowID = db.insert(TASK_TABLE, null, cv);
this.closeDB();
return rowID;
public int updateTask(Task task)
ContentValues cv = new ContentValues();
cv.put(TASK_LIST_ID, task.getListId());
cv.put(TASK_NAME, task.getName());
String where = TASK_ID + "= ?";
String[] whereArgs = String.valueOf(task.getId()) ;
this.openWriteableDB();
int rowCount = db.update(TASK_TABLE, cv, where, whereArgs);
this.closeDB();
return rowCount;
public int deleteTask(long id)
String where = TASK_ID + "= ?";
String[] whereArgs = String.valueOf(id) ;
this.openWriteableDB();
int rowCount = db.delete(TASK_TABLE, where, whereArgs);
this.closeDB();
return rowCount;
这是我的课程的一个非常简化的版本,使用我在网上找到的一些代码构建。在这个例子中,我只展示了我的两个表的代码:List 和 Task,以及 Task 表的一些 sql 方法:insertTask、updateTask 和 deleteTask。
即使上面显示的代码有效,但我认为将所有代码用于假设十个表都在同一个类中并不好。所以我试图将所有这些代码分成几个类,每个表一个类。像这样:
public class MyDatabaseDB
// database constants
public static final String DB_NAME = "mydatabase.db";
public static final int DB_VERSION = 1;
private static class DBHelper extends SQLiteOpenHelper
public DBHelper(Context context, String name,
CursorFactory factory, int version)
super(context, name, factory, version);
@Override
public void onCreate(SQLiteDatabase db)
// create tables
db.execSQL(ListDAL.CREATE_LIST_TABLE);
db.execSQL(TaskDAL.CREATE_TASK_TABLE);
// insert lists
db.execSQL("INSERT INTO list VALUES (1, 'Hobbies')");
db.execSQL("INSERT INTO list VALUES (2, 'Sports')");
// insert sample tasks
db.execSQL("INSERT INTO task VALUES (1, 1, 'Play the guitar')");
db.execSQL("INSERT INTO task VALUES (2, 1, 'Play video games')");
@Override
public void onUpgrade(SQLiteDatabase db,
int oldVersion, int newVersion)
Log.d("Task list", "Upgrading db from version "
+ oldVersion + " to " + newVersion);
db.execSQL(ListDAL.DROP_LIST_TABLE);
db.execSQL(TaskDAL.DROP_TASK_TABLE);
onCreate(db);
// database object and database helper object
private SQLiteDatabase db;
private DBHelper dbHelper;
// constructor
public MyDatabaseDB(Context context)
dbHelper = new DBHelper(context, DB_NAME, null, DB_VERSION);
// private methods
private void openReadableDB()
db = dbHelper.getReadableDatabase();
private void openWriteableDB()
db = dbHelper.getWritableDatabase();
private void closeDB()
if (db != null)
db.close();
这是我创建的两个新类,用于放置与特定表相关的代码:
ListDAL 没有太多代码
public class ListDAL
// list table constants
public static final String LIST_TABLE = "list";
public static final String LIST_ID = "_id";
public static final int LIST_ID_COL = 0;
public static final String LIST_NAME = "list_name";
public static final int LIST_NAME_COL = 1;
// CREATE and DROP TABLE statements
public static final String CREATE_LIST_TABLE =
"CREATE TABLE " + LIST_TABLE + " (" +
LIST_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
LIST_NAME + " TEXT UNIQUE)";
public static final String DROP_LIST_TABLE =
"DROP TABLE IF EXISTS " + LIST_TABLE;
TaskDAL 类是包含大部分代码的类,在这个类中我遇到了问题,特别是在 insertTask,updateTask 和 deleteTask 中this.openWriteableDB(),this.openWriteableDB() 之类的调用或 db.insert(TASK_TABLE, null, cv) 之类的调用。
由于这些方法不再在 TaskDAL 中,我无法访问它们。 我尝试传递一些对这些方法的引用以代替 this 或 db,但它不起作用
public class TaskDAL
// task table constants
public static final String TASK_TABLE = "task";
public static final String TASK_ID = "_id";
public static final int TASK_ID_COL = 0;
public static final String TASK_LIST_ID = "list_id";
public static final int TASK_LIST_ID_COL = 1;
public static final String TASK_NAME = "task_name";
public static final int TASK_NAME_COL = 2;
// CREATE and DROP TABLE statements
public static final String CREATE_TASK_TABLE =
"CREATE TABLE " + TASK_TABLE + " (" +
TASK_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
TASK_LIST_ID + " INTEGER, " +
TASK_NAME + " TEXT " +
)";
public static final String DROP_TASK_TABLE =
"DROP TABLE IF EXISTS " + TASK_TABLE;
// public methods
public long insertTask(Task task)
ContentValues cv = new ContentValues();
cv.put(TASK_LIST_ID, task.getListId());
cv.put(TASK_NAME, task.getName());
this.openWriteableDB();
long rowID = db.insert(TASK_TABLE, null, cv);
this.closeDB();
return rowID;
public int updateTask(Task task)
ContentValues cv = new ContentValues();
cv.put(TASK_LIST_ID, task.getListId());
cv.put(TASK_NAME, task.getName());
String where = TASK_ID + "= ?";
String[] whereArgs = String.valueOf(task.getId()) ;
this.openWriteableDB();
int rowCount = db.update(TASK_TABLE, cv, where, whereArgs);
this.closeDB();
return rowCount;
public int deleteTask(long id)
String where = TASK_ID + "= ?";
String[] whereArgs = String.valueOf(id) ;
this.openWriteableDB();
int rowCount = db.delete(TASK_TABLE, where, whereArgs);
this.closeDB();
return rowCount;
那么,你们中有人尝试过类似的事情吗? 如果我设法将数据库代码正确地分成几个类,我还能加入表吗??
附:请不要关闭此问题,如果您认为我做错了什么,请告诉我,我会尽力纠正它
【问题讨论】:
SQLiteOpenHelper
管理数据库,所以你应该只有一个。没有什么能阻止你创建其他类。
我知道,但是您认为您可以提供一些有关如何操作的提示吗?
@eddy 你使用内容提供者吗?在我的应用程序中,我像这样分解这段代码:一个 DBHelper、多个 PersistentContrat 和一个 ContentProvider。它显然更具可读性。如果你愿意,我可以提供你的代码示例
@FrédéricLetellier 是的,请:)
@eddy 完成!随时通知我
【参考方案1】:
你认为你可以提供一些关于如何做到这一点的提示
这与 android 无关,甚至与 Java 也没有太大关系。将较长的编程结构(例如 Java 中的类)分解为更小的结构具有称为设计模式的标准技术,并具有特定于语言的实现。
例如,您可以使用the composite pattern:
定义一个接口——在这里我称之为TableHelper
——它的onCreate()
和onUpdate()
方法与SQLiteOpenHelper
上的方法相匹配
定义 N 个类,每个表一个,实现 TableHelper
接口并为该表提供创建和升级逻辑(以及您希望在这些类上具有的任何其他业务逻辑)
让您的SQLiteOpenHelper
定义一个包含TableHelper
类实例的TableHelper[]
,并让它通过遍历数组将onCreate()
和onUpgrade()
委托给TableHelper
实例
【讨论】:
我对这个问题很感兴趣,但我没有使用过委托。你认为你可以解释一下最后一部分关于让 SQLiteOpenHelper 定义一个 TableHelper[] @Axel:有一个static
数据成员,类型为TableHelper[]
。使用static
初始化程序块用TableHelper
实现的实例填充该数组。使用依赖注入(例如,Dagger)可能有比这更清洁的方法,但我对 DI 的经验有限。虽然与SQLiteOpenHelper
无关,但this sample activity 显示静态ArrayList
和初始化块。
@CommonsWare 如果我按照你的描述实现了一些东西,我还能加入表吗??
@eddy: JOIN
是您在查询中执行的操作。 SQLiteOpenHelper
不涉及查询,除了它设置您执行查询的表的程度。您将查询代码放在哪里取决于您。
@CommonsWare 我明白了,我稍后再试一试,看看会发生什么。非常感谢【参考方案2】:
使用 Content Provider,您可以将长 SQLiteOpenHelper 拆分为多个文件:每个表一个 persistenceContract,一个小的 SQLiteOpenHelper,以及长而详细的 ContentProvider。
使用此解决方案,您需要编写更多代码。但它更具可读性,并且易于维护。
优点:
编写查询时轻松命名表的列(例如:TaskPersistenceContract.TaskEntry.COLUMN_TASK_NAME) 易于阅读和维护 减少拼写错误 使用游标和 CursorLoader 逻辑缺点:
更详细让我们试试你的初始代码吧!
1.为每个表创建一个 PersistenceContract
ListPersistenceContract:
public final class ListPersistenceContract
public static final String CONTENT_AUTHORITY = BuildConfig.APPLICATION_ID;
public static final String CONTENT_LIST_TYPE = "vnd.android.cursor.dir/" + CONTENT_AUTHORITY + "/" + ListEntry.TABLE_NAME;
public static final String CONTENT_LIST_ITEM_TYPE = "vnd.android.cursor.item/" + CONTENT_AUTHORITY + "/" + ListEntry.TABLE_NAME;
public static final String VND_ANDROID_CURSOR_ITEM_VND = "vnd.android.cursor.item/vnd." + CONTENT_AUTHORITY + ".";
private static final String CONTENT_SCHEME = "content://";
public static final Uri BASE_CONTENT_URI = Uri.parse(CONTENT_SCHEME + CONTENT_AUTHORITY);
private static final String VND_ANDROID_CURSOR_DIR_VND = "vnd.android.cursor.dir/vnd." + CONTENT_AUTHORITY + ".";
private static final String SEPARATOR = "/";
// To prevent someone from accidentally instantiating the contract class,
// give it an empty constructor.
private ListPersistenceContract()
public static Uri getBaseListUri(String listId)
return Uri.parse(CONTENT_SCHEME + CONTENT_LIST_ITEM_TYPE + SEPARATOR + listId);
/* Inner class that defines the table contents */
public static abstract class ListEntry implements BaseColumns
public static final String TABLE_NAME = "list";
public static final String COLUMN_LIST_NAME = "list_name";
public static final Uri CONTENT_LIST_URI = BASE_CONTENT_URI.buildUpon().appendPath(TABLE_NAME).build();
public static String[] LIST_COLUMNS = new String[]
ListPersistenceContract.ListEntry._ID,
ListEntry.COLUMN_LIST_NAME;
public static final String LIST_AND_TASK = "listandtask";
public static Uri buildListUriWith(long id)
return ContentUris.withAppendedId(CONTENT_LIST_URI, id);
public static Uri buildListUriWith(String id)
Uri uri = CONTENT_LIST_URI.buildUpon().appendPath(id).build();
return uri;
public static Uri buildListUri()
return CONTENT_LIST_URI.buildUpon().build();
public static Uri buildListAndTaskUri()
return BASE_CONTENT_URI.buildUpon().appendPath(ListEntry.LIST_AND_TASK).build();
TaskPersistenceContract:
public class TaskPersistenceContract
public static final String CONTENT_AUTHORITY = BuildConfig.APPLICATION_ID;
public static final String CONTENT_TASK_TYPE = "vnd.android.cursor.dir/" + CONTENT_AUTHORITY + "/" + TaskEntry.TABLE_NAME;
public static final String CONTENT_TASK_ITEM_TYPE = "vnd.android.cursor.item/" + CONTENT_AUTHORITY + "/" + TaskEntry.TABLE_NAME;
public static final String VND_ANDROID_CURSOR_ITEM_VND = "vnd.android.cursor.item/vnd." + CONTENT_AUTHORITY + ".";
private static final String CONTENT_SCHEME = "content://";
public static final Uri BASE_CONTENT_URI = Uri.parse(CONTENT_SCHEME + CONTENT_AUTHORITY);
private static final String VND_ANDROID_CURSOR_DIR_VND = "vnd.android.cursor.dir/vnd." + CONTENT_AUTHORITY + ".";
private static final String SEPARATOR = "/";
// To prevent someone from accidentally instantiating the contract class,
// give it an empty constructor.
private TaskPersistenceContract()
public static Uri getBaseTaskUri(String taskId)
return Uri.parse(CONTENT_SCHEME + CONTENT_TASK_ITEM_TYPE + SEPARATOR + taskId);
/* Inner class that defines the table contents */
public static abstract class TaskEntry implements BaseColumns
public static final String TABLE_NAME = "task";
public static final String COLUMN_TASK_LIST_ID = "list_id";
public static final String COLUMN_TASK_NAME = "task_name";
public static final Uri CONTENT_TASK_URI = BASE_CONTENT_URI.buildUpon().appendPath(TABLE_NAME).build();
public static String[] TASK_COLUMNS = new String[]
TaskPersistenceContract.TaskEntry._ID,
TaskPersistenceContract.TaskEntry.COLUMN_TASK_LIST_ID,
TaskPersistenceContract.TaskEntry.COLUMN_TASK_NAME;
public static Uri buildTaskUriWith(long id)
return ContentUris.withAppendedId(CONTENT_TASK_URI, id);
public static Uri buildTaskUriWith(String id)
Uri uri = CONTENT_TASK_URI.buildUpon().appendPath(id).build();
return uri;
public static Uri buildTaskUri()
return CONTENT_TASK_URI.buildUpon().build();
2。创建 DbHelper
public class LocalDbHelper
public static final int DB_VERSION = 1;
public static final String DB_NAME = "mydatabase.db";
private static final String TEXT_TYPE = " TEXT";
private static final String INTEGER_TYPE = " INTEGER";
private static final String PRIMARY_KEY = " PRIMARY KEY";
private static final String AUTOINCREMENT = " AUTOINCREMENT";
private static final String UNIQUE = " UNIQUE";
private static final String CREATE_TABLE = "CREATE TABLE ";
private static final String DROP_TABLE_IF_EXISTS = "DROP TABLE IF EXISTS ";
private static final String OPEN_PARENTHESIS = " (";
private static final String CLOSE_PARENTHESIS = " )";
private static final String COMMA_SEP = ",";
private static final String CREATE_LIST_TABLE =
CREATE_TABLE + ListPersistenceContract.ListEntry.TABLE_NAME + OPEN_PARENTHESIS +
ListPersistenceContract.ListEntry._ID + INTEGER_TYPE + PRIMARY_KEY + AUTOINCREMENT + COMMA_SEP +
ListPersistenceContract.ListEntry.COLUMN_LIST_NAME + TEXT_TYPE + UNIQUE +
CLOSE_PARENTHESIS;
private static final String CREATE_TASK_TABLE =
CREATE_TABLE + TaskPersistenceContract.TaskEntry.TABLE_NAME + OPEN_PARENTHESIS +
TaskPersistenceContract.TaskEntry._ID + INTEGER_TYPE + PRIMARY_KEY + AUTOINCREMENT + COMMA_SEP +
TaskPersistenceContract.TaskEntry.COLUMN_TASK_LIST_ID + INTEGER_TYPE + COMMA_SEP +
TaskPersistenceContract.TaskEntry.COLUMN_TASK_NAME + TEXT_TYPE +
CLOSE_PARENTHESIS;
private static final String DROP_LIST_TABLE =
DROP_TABLE_IF_EXISTS + ListPersistenceContract.ListEntry.TABLE_NAME;
private static final String DROP_TASK_TABLE =
DROP_TABLE_IF_EXISTS + TaskPersistenceContract.TaskEntry.TABLE_NAME;
public LocalDbHelper(Context context)
super(context, DB_NAME, null, DB_VERSION);
public void onCreate(SQLiteDatabase db)
// create tables
db.execSQL(CREATE_LIST_TABLE);
db.execSQL(CREATE_TASK_TABLE);
// insert lists
db.execSQL("INSERT INTO " + ListPersistenceContract.ListEntry.TABLE_NAME + " VALUES (1, 'Hobbies')");
db.execSQL("INSERT INTO " + ListPersistenceContract.ListEntry.TABLE_NAME + " VALUES (2, 'Sports')");
// insert sample tasks
db.execSQL("INSERT INTO " + TaskPersistenceContract.TaskEntry.TABLE_NAME + " VALUES (1, 1, 'Play the guitar')");
db.execSQL("INSERT INTO " + TaskPersistenceContract.TaskEntry.TABLE_NAME + " VALUES (2, 1, 'Play video games')");
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
Log.d("Task list", "Upgrading db from version "
+ oldVersion + " to " + newVersion);
db.execSQL(LocalDbHelper.DROP_LIST_TABLE);
db.execSQL(LocalDbHelper.DROP_TASK_TABLE);
onCreate(db);
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion)
// Not required as at version 1
3.创建具有查询、插入、更新和删除操作的 ContentProvider
(在本例中,我为查询添加了一个表连接。您可以对插入、更新和删除操作使用相同的逻辑。)
public class MyAppContentProvider extends ContentProvider
private static final int LIST = 100;
private static final int LIST_ITEM = 101;
private static final int LIST_AND_TASK = 102;
private static final int TASK = 200;
private static final int TASK_ITEM = 201;
private static final UriMatcher sUriMatcher = buildUriMatcher();
private LocalDbHelper mLocalDbHelper;
private static final SQLiteQueryBuilder sListAndTask;
static
sListAndTask = new SQLiteQueryBuilder();
sListAndTask.setTables(
ListPersistenceContract.ListEntry.TABLE_NAME + " INNER JOIN " +
TaskPersistenceContract.TaskEntry.TABLE_NAME +
" ON " + ListPersistenceContract.ListEntry.TABLE_NAME +
"." + ListPersistenceContract.ListEntry._ID +
" = " + TaskPersistenceContract.TaskEntry.TABLE_NAME +
"." + TaskPersistenceContract.TaskEntry.COLUMN_TASK_LIST_ID);
private static UriMatcher buildUriMatcher()
final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
final String authority = ListPersistenceContract.CONTENT_AUTHORITY;
matcher.addURI(authority, ListPersistenceContract.ListEntry.TABLE_NAME, LIST);
matcher.addURI(authority, ListPersistenceContract.ListEntry.TABLE_NAME + "/*", LIST_ITEM);
matcher.addURI(authority, ListPersistenceContract.ListEntry.LIST_AND_TASK, LIST_AND_TASK);
matcher.addURI(authority, TaskPersistenceContract.TaskEntry.TABLE_NAME, TASK);
matcher.addURI(authority, TaskPersistenceContract.TaskEntry.TABLE_NAME + "/*", TASK_ITEM);
return matcher;
@Override
public boolean onCreate()
mLocalDbHelper = new LocalDbHelper(getContext());
return true;
@Nullable
@Override
public String getType(Uri uri)
final int match = sUriMatcher.match(uri);
switch (match)
case LIST:
return ListPersistenceContract.CONTENT_LIST_TYPE;
case LIST_ITEM:
return ListPersistenceContract.CONTENT_LIST_ITEM_TYPE;
case TASK:
return TaskPersistenceContract.CONTENT_TASK_TYPE;
case TASK_ITEM:
return TaskPersistenceContract.CONTENT_TASK_ITEM_TYPE;
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
@Nullable
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
Cursor retCursor;
switch (sUriMatcher.match(uri))
case LIST:
retCursor = mLocalDbHelper.getReadableDatabase().query(
ListPersistenceContract.ListEntry.TABLE_NAME,
projection,
selection,
selectionArgs,
null,
null,
sortOrder
);
break;
case LIST_ITEM:
String[] where_list = uri.getLastPathSegment();
retCursor = mLocalDbHelper.getReadableDatabase().query(
ListPersistenceContract.ListEntry.TABLE_NAME,
projection,
ListPersistenceContract.ListEntry._ID + " = ?",
where_list,
null,
null,
sortOrder
);
break;
case LIST_AND_TASK:
retCursor = sListAndTask.query(mLocalDbHelper.getReadableDatabase(),
projection,
selection,
selectionArgs,
null,
null,
sortOrder
);
break;
case TASK:
retCursor = mLocalDbHelper.getReadableDatabase().query(
TaskPersistenceContract.TaskEntry.TABLE_NAME,
projection,
selection,
selectionArgs,
null,
null,
sortOrder
);
break;
case TASK_ITEM:
String[] where_task = uri.getLastPathSegment();
retCursor = mLocalDbHelper.getReadableDatabase().query(
TaskPersistenceContract.TaskEntry.TABLE_NAME,
projection,
TaskPersistenceContract.TaskEntry._ID + " = ?",
where_task,
null,
null,
sortOrder
);
break;
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
retCursor.setNotificationUri(getContext().getContentResolver(), uri);
return retCursor;
@Nullable
@Override
public Uri insert(Uri uri, ContentValues values)
final SQLiteDatabase db = mLocalDbHelper.getWritableDatabase();
final int match = sUriMatcher.match(uri);
Uri returnUri;
Cursor exists;
switch (match)
case LIST:
exists = db.query(
ListPersistenceContract.ListEntry.TABLE_NAME,
new String[]ListPersistenceContract.ListEntry._ID,
ListPersistenceContract.ListEntry._ID + " = ?",
new String[]values.getAsString(ListPersistenceContract.ListEntry._ID),
null,
null,
null
);
if (exists.moveToLast())
long _id = db.update(
ListPersistenceContract.ListEntry.TABLE_NAME, values,
ListPersistenceContract.ListEntry._ID + " = ?",
new String[]values.getAsString(ListPersistenceContract.ListEntry._ID)
);
if (_id > 0)
returnUri = ListPersistenceContract.ListEntry.buildListUriWith(_id);
else
throw new android.database.SQLException("Failed to insert row into " + uri);
else
long _id = db.insert(ListPersistenceContract.ListEntry.TABLE_NAME, null, values);
if (_id > 0)
returnUri = ListPersistenceContract.ListEntry.buildListUriWith(_id);
else
throw new android.database.SQLException("Failed to insert row into " + uri);
exists.close();
break;
case TASK:
exists = db.query(
TaskPersistenceContract.TaskEntry.TABLE_NAME,
new String[]TaskPersistenceContract.TaskEntry._ID,
TaskPersistenceContract.TaskEntry._ID + " = ?",
new String[]values.getAsString(TaskPersistenceContract.TaskEntry._ID),
null,
null,
null
);
if (exists.moveToLast())
long _id = db.update(
TaskPersistenceContract.TaskEntry.TABLE_NAME, values,
TaskPersistenceContract.TaskEntry._ID + " = ?",
new String[]values.getAsString(TaskPersistenceContract.TaskEntry._ID)
);
if (_id > 0)
returnUri = TaskPersistenceContract.TaskEntry.buildTaskUriWith(_id);
else
throw new android.database.SQLException("Failed to insert row into " + uri);
else
long _id = db.insert(TaskPersistenceContract.TaskEntry.TABLE_NAME, null, values);
if (_id > 0)
returnUri = TaskPersistenceContract.TaskEntry.buildTaskUriWith(_id);
else
throw new android.database.SQLException("Failed to insert row into " + uri);
exists.close();
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)
final SQLiteDatabase db = mLocalDbHelper.getWritableDatabase();
final int match = sUriMatcher.match(uri);
int rowsDeleted;
switch (match)
case LIST:
rowsDeleted = db.delete(
ListPersistenceContract.ListEntry.TABLE_NAME, selection, selectionArgs);
break;
case TASK:
rowsDeleted = db.delete(
TaskPersistenceContract.TaskEntry.TABLE_NAME, selection, selectionArgs);
break;
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
if (selection == null || rowsDeleted != 0)
getContext().getContentResolver().notifyChange(uri, null);
return rowsDeleted;
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
final SQLiteDatabase db = mLocalDbHelper.getWritableDatabase();
final int match = sUriMatcher.match(uri);
int rowsUpdated;
switch (match)
case LIST:
rowsUpdated = db.update(ListPersistenceContract.ListEntry.TABLE_NAME, values, selection,
selectionArgs
);
break;
case TASK:
rowsUpdated = db.update(TaskPersistenceContract.TaskEntry.TABLE_NAME, values, selection,
selectionArgs
);
break;
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
if (rowsUpdated != 0)
getContext().getContentResolver().notifyChange(uri, null);
return rowsUpdated;
【讨论】:
以上是关于如何将一个长的单个 SQLiteOpenHelper 拆分为多个类,每个表一个类的主要内容,如果未能解决你的问题,请参考以下文章
在更长的字符串中,如何在 PostgreSQL(和/或 Python 3)中将一个字符(例如,'a')和一个变音字符(例如,'U+030A')转换为单个字符('å')[重复]