/** * Listing 8-14: A skeleton Content Provider implementation */ package com.paad.DatabaseSkeleton; import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.content.UriMatcher; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteException; import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; import android.text.TextUtils; import android.util.Log; public class MyContentProvider extends ContentProvider { public static final Uri CONTENT_URI = Uri.parse("content://com.paad.skeletondatabaseprovider/elements"); /** * Listing 8-8: Defining a UriMatcher to determine if a request is for all elements or a single row */ //Create the constants used to differentiate between the different URI //requests. 创建两个常量来区分不同的URI请求 private static final int ALLROWS = 1; private static final int SINGLE_ROW = 2; private static final UriMatcher uriMatcher; //Populate the UriMatcher object, where a URI ending in 填充UriMatcher对象,其中以elements结尾请求所有数据 //'elements' will correspond to a request for all items, //and 'elements/[rowID]' represents a single row. 以elements/[rowID]结尾的请求单行数据 static { uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); uriMatcher.addURI("com.paad.skeletondatabaseprovider", "elements", ALLROWS); uriMatcher.addURI("com.paad.skeletondatabaseprovider", "elements/#", SINGLE_ROW); } /** */ // The index (key) column name for use in where clauses. public static final String KEY_ID = "_id"; // The name and column index of each column in your database. // These should be descriptive. public static final String KEY_COLUMN_1_NAME = "KEY_COLUMN_1_NAME"; // TODO: Create public field for each column in your table. /** * Listing 8-9: Creating the Content Provider�s database */ private MySQLiteOpenHelper myOpenHelper; @Override public boolean onCreate() { // Construct the underlying database. 构造底层数据库 // Defer opening the database until you need to perform 延迟打开数据库,直到需要执行 // a query or transaction. 一个查询或者事务时再打开 myOpenHelper = new MySQLiteOpenHelper(getContext(), MySQLiteOpenHelper.DATABASE_NAME, null, MySQLiteOpenHelper.DATABASE_VERSION); return true; } /** * Listing 8-10: Implementing queries and transactions within a Content Provider */ @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // Open thedatabase. 打开数据库 SQLiteDatabase db; try { db = myOpenHelper.getWritableDatabase(); } catch (SQLiteException ex) { db = myOpenHelper.getReadableDatabase(); } // Replace these with valid SQL statements if necessary. 必要的话使用有效的SQL语句替换这些语句 String groupBy = null; String having = null; // Use an SQLite Query Builder to simplify constructing the // database query.用Query Builder 来简化构造数据库查询的过程 SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); // If this is a row query, limit the result set to the passed in row. switch (uriMatcher.match(uri)) { case SINGLE_ROW : String rowID = uri.getPathSegments().get(1); queryBuilder.appendWhere(KEY_ID + "=" + rowID); default: break; } // Specify the table on which to perform the query. This can // be a specific table or a join as required. 制定要执行查询的表 queryBuilder.setTables(MySQLiteOpenHelper.DATABASE_TABLE); // Execute the query. 执行查询 Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, groupBy, having, sortOrder); // Return the result Cursor. 返回结果Cursor return cursor; } /** * Listing 8-11: Returning a Content Provider MIME type 返回一个MIME类型来标识返回的数据 */ @Override public String getType(Uri uri) { // Return a string that identifies the MIME type // for a Content Provider URI switch (uriMatcher.match(uri)) { case ALLROWS: return "vnd.android.cursor.dir/vnd.paad.elemental"; case SINGLE_ROW: return "vnd.android.cursor.item/vnd.paad.elemental"; default: throw new IllegalArgumentException("Unsupported URI: " + uri); } } /** * Listing 8-12: Typical Content Provider transaction implementations */ @Override public int delete(Uri uri, String selection, String[] selectionArgs) { // Open a read / write database to support the transaction. 打开一个可读可写的数据库来支持事务 SQLiteDatabase db = myOpenHelper.getWritableDatabase(); // If this is a row URI, limit the deletion to the specified row. 限定删除的行为为指定的行 switch (uriMatcher.match(uri)) { case SINGLE_ROW : String rowID = uri.getPathSegments().get(1); selection = KEY_ID + "=" + rowID + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""); default: break; } // To return the number of deleted items you must specify a where // clause. To delete all rows and return a value pass in "1". 要想返回删除的项的数量,必须制定一条where字句。要删除所有行并返回一个值,则传入1 if (selection == null) selection = "1"; // Perform the deletion. 执行删除 int deleteCount = db.delete(MySQLiteOpenHelper.DATABASE_TABLE, selection, selectionArgs); // Notify any observers of the change in the data set. 通知所有观察者,数据集已经改变 getContext().getContentResolver().notifyChange(uri, null); // Return the number of deleted items. 返回删除的项的数量 return deleteCount; } @Override public Uri insert(Uri uri, ContentValues values) { // Open a read / write database to support the transaction. 打开一个可读可写的数据库来支持事务 SQLiteDatabase db = myOpenHelper.getWritableDatabase(); // To add empty rows to your database by passing in an empty // Content Values object you must use the null column hack // parameter to specify the name of the column that can be // set to null. 要想通过传入一个空content value对象来向数据库添加一个空行,必须使用nullColumnHack参数来制定可以设置为null的列名 String nullColumnHack = null; // Insert the values into the table 向表中插入数据 long id = db.insert(MySQLiteOpenHelper.DATABASE_TABLE, nullColumnHack, values); // Construct and return the URI of the newly inserted row. 构造并返回新插入的行的URI if (id > -1) { // Construct and return the URI of the newly inserted row. Uri insertedId = ContentUris.withAppendedId(CONTENT_URI, id); // Notify any observers of the change in the data set. getContext().getContentResolver().notifyChange(insertedId, null); return insertedId; } else return null; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { // Open a read / write database to support the transaction. SQLiteDatabase db = myOpenHelper.getWritableDatabase(); // If this is a row URI, limit the deletion to the specified row. switch (uriMatcher.match(uri)) { case SINGLE_ROW : String rowID = uri.getPathSegments().get(1); selection = KEY_ID + "=" + rowID + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""); default: break; } // Perform the update. int updateCount = db.update(MySQLiteOpenHelper.DATABASE_TABLE, values, selection, selectionArgs); // Notify any observers of the change in the data set. getContext().getContentResolver().notifyChange(uri, null); return updateCount; } private static class MySQLiteOpenHelper extends SQLiteOpenHelper { // Database name, version, and table names. private static final String DATABASE_NAME = "myDatabase.db"; private static final int DATABASE_VERSION = 1; private static final String DATABASE_TABLE = "mainTable"; // SQL Statement to create a new database. private static final String DATABASE_CREATE = "create table " + DATABASE_TABLE + " (" + KEY_ID + " integer primary key autoincrement, " + KEY_COLUMN_1_NAME + " text not null);"; public MySQLiteOpenHelper(Context context, String name, CursorFactory factory, int version) { super(context, name, factory, version); } // Called when no database exists in disk and the helper class needs // to create a new one. @Override public void onCreate(SQLiteDatabase _db) { _db.execSQL(DATABASE_CREATE); } // Called when there is a database version mismatch meaning that the version // of the database on disk needs to be upgraded to the current version. @Override public void onUpgrade(SQLiteDatabase _db, int _oldVersion, int _newVersion) { // Log the version upgrade. Log.w("TaskDBAdapter", "Upgrading from version " + _oldVersion + " to " + _newVersion + ", which will destroy all old data"); // Upgrade the existing database to conform to the new version. Multiple // previous versions can be handled by comparing _oldVersion and _newVersion // values. // The simplest case is to drop the old table and create a new one. _db.execSQL("DROP TABLE IF IT EXISTS " + DATABASE_TABLE); // Create a new one. onCreate(_db); } } }