第八章-数据库和Content Provider----ContentProvider工具类

/**
 * 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);
    }
  }
}


你可能感兴趣的:(第八章-数据库和Content Provider----ContentProvider工具类)