如何将一个长的单个 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,updateTaskdeleteTaskthis.openWriteableDB(),this.openWriteableDB() 之类的调用或 db.insert(TASK_TABLE, null, cv) 之类的调用。

由于这些方法不再在 TaskDAL 中,我无法访问它们。 我尝试传递一些对这些方法的引用以代替 thisdb,但它不起作用

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')转换为单个字符('å')[重复]

如何在不冻结 GUI 的情况下在单个插槽中实现阻塞进程?

分层mp3曲目[关闭]

Solidworks如何把装配体做成单个零件

即使我切换了活动,如何在活动中播放单个音频文件?

如何在多个页面中拆分长的 symfony 表单?