使用一个ContentProvider操作多张表

来源:互联网 发布:日本好用护肤品知乎 编辑:程序博客网 时间:2024/05/16 05:08

使用一个ContentProvider操作多张表

在我们开发过程中,通常使用ContentProvider来操作数据。查询数据库中的一张表的数据我们创建一个ContentProvider提供操作,需要访问多张表中的数据时,可以创建多个对应的ContentProvider来操作数据。

当然,如果只用一个ContentProvider来操作同一个数据库中的多张表也是可以实现的。ContentProvider所提供的CRUD方法都是通过uri来实现,使用一个ContentProvider操作多张表,也就是说一个authority,然后多个CONTENT_URI对应多张表。思路大概就是这样子,下面给出代码,代码是在NotePad源码上做了修改:

NotePad类(契约类)中声明AUTHORITY,class Notes对应数据库中的Notes表,class NotesGroup对应 NotesGroup表,它们有各自的CONTENT_URI。

NotePad.java

public final class NotePad {    public static final String AUTHORITY = "com.google.provider.NotePad";    // This class cannot be instantiated    private NotePad() {    }    /**     * Notes table contract     */    public static final class Notes implements BaseColumns {        // This class cannot be instantiated        private Notes() {}        /**         * The table name offered by this provider         */        public static final String TABLE_NAME = "notes";        /*         * URI definitions         */        /**         * The scheme part for this provider's URI         */        private static final String SCHEME = "content://";        /**         * Path parts for the URIs         */        /**         * Path part for the Notes URI         */        private static final String PATH_NOTES = "/notes";        /**         * Path part for the Note ID URI         */        private static final String PATH_NOTE_ID = "/notes/";        /**         * 0-relative position of a note ID segment in the path part of a note ID URI         */        public static final int NOTE_ID_PATH_POSITION = 1;        /**         * Path part for the Live Folder URI         */        private static final String PATH_LIVE_FOLDER = "/live_folders/notes";        /**         * The content:// style URL for this table         */        public static final Uri CONTENT_URI =  Uri.parse(SCHEME + AUTHORITY + PATH_NOTES);        /**         * The content URI base for a single note. Callers must         * append a numeric note id to this Uri to retrieve a note         */        public static final Uri CONTENT_ID_URI_BASE            = Uri.parse(SCHEME + AUTHORITY + PATH_NOTE_ID);        /**         * The content URI match pattern for a single note, specified by its ID. Use this to match         * incoming URIs or to construct an Intent.         */        public static final Uri CONTENT_ID_URI_PATTERN            = Uri.parse(SCHEME + AUTHORITY + PATH_NOTE_ID + "/#");        /**         * The content Uri pattern for a notes listing for live folders         */        public static final Uri LIVE_FOLDER_URI            = Uri.parse(SCHEME + AUTHORITY + PATH_LIVE_FOLDER);        /*         * MIME type definitions         */        /**         * The MIME type of {@link #CONTENT_URI} providing a directory of notes.         */        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.google.note";        /**         * The MIME type of a {@link #CONTENT_URI} sub-directory of a single         * note.         */        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.google.note";        /**         * The default sort order for this table         */        public static final String DEFAULT_SORT_ORDER = "modified DESC";        /*         * Column definitions         */        /**         * Column name for the title of the note         * <P>Type: TEXT</P>         */        public static final String COLUMN_NAME_TITLE = "title";        /**         * Column name of the note content         * <P>Type: TEXT</P>         */        public static final String COLUMN_NAME_NOTE = "note";        /**         * Column name for the creation timestamp         * <P>Type: INTEGER (long from System.curentTimeMillis())</P>         */        public static final String COLUMN_NAME_CREATE_DATE = "created";        /**         * Column name for the modification timestamp         * <P>Type: INTEGER (long from System.curentTimeMillis())</P>         */        public static final String COLUMN_NAME_MODIFICATION_DATE = "modified";        public static final String COLUMN_NAME_GROUPID = "gid";    }    public static final class NotesGroup implements BaseColumns {        private NotesGroup(){}        public static final String TABLE_NAME = "notesGroup";        private static final String SCHEME = "content://";        private static final String PATH_NOTES_GROUP = "/notesGroup";        private static final String PATH_NOTEGROUP_ID = "/notesGroup/";        /**         * 0-relative position of a note ID segment in the path part of a note ID URI         */        public static final int NOTE_ID_PATH_POSITION = 1;        /**         * The content:// style URL for this table         */        public static final Uri CONTENT_URI =  Uri.parse(SCHEME + AUTHORITY + PATH_NOTES_GROUP);        public static final Uri CONTENT_ID_URI_BASE                = Uri.parse(SCHEME + AUTHORITY + PATH_NOTEGROUP_ID);        public static final Uri CONTENT_ID_URI_PATTERN                = Uri.parse(SCHEME + AUTHORITY + PATH_NOTEGROUP_ID + "/#");        public static final String COLUMN_NAME_GROUPTITLE = "name";    }

1、在自定义ContentProvider类给sUriMatcher添加匹配项(两张表的匹配)

//Notes表private static final int NOTES = 1;private static final int NOTE_ID = 2;//NotesGroup表private static final int NotesGroup = 4;private static final int NotesGroup_ID = 5;sUriMatcher.addURI(NotePad.AUTHORITY, "notes", NOTES);sUriMatcher.addURI(NotePad.AUTHORITY, "notes/#", NOTE_ID);sUriMatcher.addURI(NotePad.AUTHORITY, "notesGroup", NotesGroup);sUriMatcher.addURI(NotePad.AUTHORITY, "notesGroup/#", NotesGroup_ID);

2、在CRUD操作代码(根据匹配项分别操作两张表)

  @Override   public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,           String sortOrder) {       // Constructs a new query builder and sets its table name       SQLiteQueryBuilder qb = new SQLiteQueryBuilder();       String orderBy = null;       switch (sUriMatcher.match(uri)) {           // If the incoming URI is for notes, chooses the Notes projection           case NOTES:               qb.setTables(NotePad.Notes.TABLE_NAME);               qb.setProjectionMap(sNotesProjectionMap);               // If no sort order is specified, uses the default               if (TextUtils.isEmpty(sortOrder)) {                   orderBy = NotePad.Notes.DEFAULT_SORT_ORDER;               } else {                   // otherwise, uses the incoming sort order                   orderBy = sortOrder;               }               break;           case NOTE_ID:               qb.setTables(NotePad.Notes.TABLE_NAME);               qb.setProjectionMap(sNotesProjectionMap);               qb.appendWhere(                   NotePad.Notes._ID +    // the name of the ID column                   "=" +                   uri.getPathSegments().get(NotePad.Notes.NOTE_ID_PATH_POSITION));               if (TextUtils.isEmpty(sortOrder)) {                   orderBy = NotePad.Notes.DEFAULT_SORT_ORDER;               } else {                   // otherwise, uses the incoming sort order                   orderBy = sortOrder;               }               break;           //=====================================           case NotesGroup:               qb.setTables(NotePad.NotesGroup.TABLE_NAME);               qb.setProjectionMap(sGroupProjectionMap);               break;           case NotesGroup_ID:               qb.setTables(NotePad.NotesGroup.TABLE_NAME);               qb.appendWhere(NotePad.NotesGroup._ID + "=" + uri.getPathSegments().get(NotePad.NotesGroup.NOTE_ID_PATH_POSITION));               break;           default:               throw new IllegalArgumentException("Unknown URI " + uri);       }       SQLiteDatabase db = mOpenHelper.getReadableDatabase();       Cursor c = qb.query(           db,            // The database to query           projection,    // The columns to return from the query           selection,     // The columns for the where clause           selectionArgs, // The values for the where clause           null,          // don't group the rows           null,          // don't filter by row groups           orderBy        // The sort order       );       c.setNotificationUri(getContext().getContentResolver(), uri);       return c;   }

NotePadProvider类代码,代码中只给出query方法,其他操作方法按照同样思路写

NotePadProvider.java

public class NotePadProvider extends ContentProvider implements PipeDataWriter<Cursor> {    private static final String TAG = "NotePadProvider";    private static final String DATABASE_NAME = "note_pad.db";    private static final int DATABASE_VERSION = 2;    private static HashMap<String, String> sNotesProjectionMap;    private static HashMap<String,String> sGroupProjectionMap;    private static final String[] READ_NOTE_PROJECTION = new String[] {            NotePad.Notes._ID,               // Projection position 0, the note's id            NotePad.Notes.COLUMN_NAME_NOTE,  // Projection position 1, the note's content            NotePad.Notes.COLUMN_NAME_TITLE, // Projection position 2, the note's title    };    private static final int READ_NOTE_NOTE_INDEX = 1;    private static final int READ_NOTE_TITLE_INDEX = 2;    private static final String[] READ_GROUP_PROJECTION = new String[]{            NotePad.NotesGroup._ID,            NotePad.NotesGroup.COLUMN_NAME_GROUPTITLE    };    private static final int READ_GROUP_GROUPTITLE_INDEX = 1;    private static final int NOTES = 1;    private static final int NOTE_ID = 2;    private static final int NotesGroup = 4;    private static final int NotesGroup_ID = 5;    private static final UriMatcher sUriMatcher;    // Handle to a new DatabaseHelper.    private DatabaseHelper mOpenHelper;    static {        // Create a new instance        sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);        // Add a pattern that routes URIs terminated with "notes" to a NOTES operation        sUriMatcher.addURI(NotePad.AUTHORITY, "notes", NOTES);        // Add a pattern that routes URIs terminated with "notes" plus an integer        // to a note ID operation        sUriMatcher.addURI(NotePad.AUTHORITY, "notes/#", NOTE_ID);        sUriMatcher.addURI(NotePad.AUTHORITY, "notesGroup", NotesGroup);        sUriMatcher.addURI(NotePad.AUTHORITY, "notesGroup/#", NotesGroup_ID);        sNotesProjectionMap = new HashMap<String, String>();        // Maps the string "_ID" to the column name "_ID"        sNotesProjectionMap.put(NotePad.Notes._ID, NotePad.Notes._ID);        // Maps "title" to "title"        sNotesProjectionMap.put(NotePad.Notes.COLUMN_NAME_TITLE, NotePad.Notes.COLUMN_NAME_TITLE);        // Maps "note" to "note"        sNotesProjectionMap.put(NotePad.Notes.COLUMN_NAME_NOTE, NotePad.Notes.COLUMN_NAME_NOTE);        // Maps "created" to "created"        sNotesProjectionMap.put(NotePad.Notes.COLUMN_NAME_CREATE_DATE,                NotePad.Notes.COLUMN_NAME_CREATE_DATE);        // Maps "modified" to "modified"        sNotesProjectionMap.put(                NotePad.Notes.COLUMN_NAME_MODIFICATION_DATE,                NotePad.Notes.COLUMN_NAME_MODIFICATION_DATE);        sNotesProjectionMap.put(NotePad.Notes.COLUMN_NAME_GROUPID,NotePad.Notes.COLUMN_NAME_GROUPID);        sGroupProjectionMap = new HashMap<String, String>();        sGroupProjectionMap.put(NotePad.NotesGroup._ID,NotePad.NotesGroup._ID);        sGroupProjectionMap.put(NotePad.NotesGroup.COLUMN_NAME_GROUPTITLE,NotePad.NotesGroup.COLUMN_NAME_GROUPTITLE);    }    /**    *    * This class helps open, create, and upgrade the database file. Set to package visibility    * for testing purposes.    */   static class DatabaseHelper extends SQLiteOpenHelper {       DatabaseHelper(Context context) {           // calls the super constructor, requesting the default cursor factory.           super(context, DATABASE_NAME, null, DATABASE_VERSION);       }       @Override       public void onCreate(SQLiteDatabase db) {           db.execSQL("CREATE TABLE " + NotePad.Notes.TABLE_NAME + " ("                   + NotePad.Notes._ID + " INTEGER PRIMARY KEY,"                   + NotePad.Notes.COLUMN_NAME_TITLE + " TEXT,"                   + NotePad.Notes.COLUMN_NAME_NOTE + " TEXT,"                   + NotePad.Notes.COLUMN_NAME_CREATE_DATE + " INTEGER,"                   + NotePad.Notes.COLUMN_NAME_MODIFICATION_DATE + " INTEGER,"                   + NotePad.Notes.COLUMN_NAME_GROUPID + " INTEGER"                   + ");");           db.execSQL("CREATE TABLE " + NotePad.NotesGroup.TABLE_NAME +" ("                   + NotePad.NotesGroup._ID + " INTEGER PRIMARY KEY,"                   + NotePad.NotesGroup.COLUMN_NAME_GROUPTITLE + " TEXT"                   + ");"           );       }       @Override       public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {           // Logs that the database is being upgraded           Log.w(TAG, "Upgrading database from version " + oldVersion + " to "                   + newVersion + ", which will destroy all old data");           // Kills the table and existing data           db.execSQL("DROP TABLE IF EXISTS notes");           db.execSQL("DROP TABLE IF EXISTS notesGroup");           // Recreates the database with a new version           onCreate(db);       }   }   @Override   public boolean onCreate() {       // Creates a new helper object. Note that the database itself isn't opened until       // something tries to access it, and it's only created if it doesn't already exist.       mOpenHelper = new DatabaseHelper(getContext());       // Assumes that any failures will be reported by a thrown exception.       return true;   }   @Override   public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,           String sortOrder) {       // Constructs a new query builder and sets its table name       SQLiteQueryBuilder qb = new SQLiteQueryBuilder();       String orderBy = null;       switch (sUriMatcher.match(uri)) {           // If the incoming URI is for notes, chooses the Notes projection           case NOTES:               qb.setTables(NotePad.Notes.TABLE_NAME);               qb.setProjectionMap(sNotesProjectionMap);               // If no sort order is specified, uses the default               if (TextUtils.isEmpty(sortOrder)) {                   orderBy = NotePad.Notes.DEFAULT_SORT_ORDER;               } else {                   // otherwise, uses the incoming sort order                   orderBy = sortOrder;               }               break;           /* If the incoming URI is for a single note identified by its ID, chooses the            * note ID projection, and appends "_ID = <noteID>" to the where clause, so that            * it selects that single note            */           case NOTE_ID:               qb.setTables(NotePad.Notes.TABLE_NAME);               qb.setProjectionMap(sNotesProjectionMap);               qb.appendWhere(                   NotePad.Notes._ID +    // the name of the ID column                   "=" +                   // the position of the note ID itself in the incoming URI                   uri.getPathSegments().get(NotePad.Notes.NOTE_ID_PATH_POSITION));               // If no sort order is specified, uses the default               if (TextUtils.isEmpty(sortOrder)) {                   orderBy = NotePad.Notes.DEFAULT_SORT_ORDER;               } else {                   // otherwise, uses the incoming sort order                   orderBy = sortOrder;               }               break;           //=====================================           case NotesGroup:               qb.setTables(NotePad.NotesGroup.TABLE_NAME);               qb.setProjectionMap(sGroupProjectionMap);               break;           case NotesGroup_ID:               qb.setTables(NotePad.NotesGroup.TABLE_NAME);               qb.appendWhere(NotePad.NotesGroup._ID + "=" + uri.getPathSegments().get(NotePad.NotesGroup.NOTE_ID_PATH_POSITION));               break;           //=======================================           case LIVE_FOLDER_NOTES:               // If the incoming URI is from a live folder, chooses the live folder projection.               qb.setProjectionMap(sLiveFolderProjectionMap);               break;           default:               // If the URI doesn't match any of the known patterns, throw an exception.               throw new IllegalArgumentException("Unknown URI " + uri);       }       // Opens the database object in "read" mode, since no writes need to be done.       SQLiteDatabase db = mOpenHelper.getReadableDatabase();       /*        * Performs the query. If no problems occur trying to read the database, then a Cursor        * object is returned; otherwise, the cursor variable contains null. If no records were        * selected, then the Cursor object is empty, and Cursor.getCount() returns 0.        */       Cursor c = qb.query(           db,            // The database to query           projection,    // The columns to return from the query           selection,     // The columns for the where clause           selectionArgs, // The values for the where clause           null,          // don't group the rows           null,          // don't filter by row groups           orderBy        // The sort order       );       // Tells the Cursor what URI to watch, so it knows when its source data changes       c.setNotificationUri(getContext().getContentResolver(), uri);       return c;   }    DatabaseHelper getOpenHelperForTest() {        return mOpenHelper;    }}

通过这种方法就可以实现使用一个ContentProvider来操作多张表,什么时候使用一个ContentProvider什么时候使用多个呢?像我呢,开发时不想多写一个ContentProvider就想到这个方法,其实看个人习惯吧。但如果数据库表中表数量变化,最好还是分开写好一点。

原创粉丝点击