ContentProvider 实例管理对一个结构型数据集的操作以处理从另外一个应用发来的请求。所有的操作最终都调用ContentResolver,然后它又调用ContentProvider 的一个具体的方法。
虚类 ContentProvider 定义了六个虚方法,你必须在你的派生类中实现它们。这些方法们,除了 onCreate() ,都会被想要操作你的content provider的客户端应用调用:
query()
从你的provider获取数据。使用参数来指定要查询的表,要返回行和列,和结果的排序方式。返回一个 Cursor 对象。
insert()
向你的provider插入一个新行。参数们指定了要选择的表和要插入的列的值。返回一个指向新行的content URI。
update()
更新你的provider中已存在的行。参数中指定了要选择的表和要更新的行以及要更新的列数据。返回更新的行的数量。
delete()
从你的provider中删除行。参数们指定了要选择是表和要删除的行们。返回删除打的行的数量。
getType()
返回对应一个content URI的MIME类型。
onCreate()
初始化你的provider。Android系统在创建你的provider之后立即调用此方法。注意你的Provider直到一个ContentResolver对象要操作它时才会被创建。
你要实现这些方法们,需要负责以上事情:
· 除了 onCreate() 所有的这些方法们都可以被多线程同时调用。所以你它们必须是多线程安全的。
· 避免在onCreate() 中进行耗时的操作。推迟初始化工作直到真正需要做的时候。
· 尽管你必须实现这些方法们,你的方法除了返回期望的数据类型外,并不是需要做所有的事情。例如,你可能想阻止其它应用向某些表中插入数据,你就可以不理会对insert() 的调用并返回0.
ContentProvider.query() 方法必须返回一个 Cursor 对象,或者,如果它失败了,抛出一个 Exception。如果你使用一个SQLite数据库作你的数据存储,你可以简单的返回从 SQLiteDatabase 类的query() 方法返回的Cursor 对象。如果查询不到任何行,你应该返回一个Cursor 的实例,但它的getCount() 方法返回0。你应该只在查询过程中发生内部错误时才返回null。
如果你不用SQLite数据库作为你的数据存储,那么需使用 Cursor的派生类。例如MatrixCursor 类,它实现了一个 cursor,cursor中的每一行都是一个Object的数组。这个类使用 addRow() 添加一个新行。
记住Android系统必须能跨进程传送Exception 。Android可以为以下异常做这些。这些异常可能在处理查询错误时有帮助:
· IllegalArgumentException (如果你的provider收到一个不合法的content URI,你可以要抛出它)
· NullPointerException
insert() 方法向适当的表添加一个新行,使用的值都存放在参数ContentValues 中。如果一个列的名字不正合适 ContentValues 参数中,你可能要为此列提供一个默认的值,这可以在provider的代码中做也可以在数据库表中做。
此方法应返回新行的content URI。要构建此URI,使用withAppendedId()向表的content URI的后面添加新行的_ID (或其它的主键)的值即可。
delete() 方法不必在物理上从你的数据存储中删除行。如果你正在为你的provider用一种同步适配器,你应该考虑把一个要删除的行打上"delete"标志而不是把行整个删除。同步适配器可以检查要被删除的行们并且在从provider中删除它们之前从server删除它们。
update() 方法带有与insert()相同的参数类型ContentValues ,以及与delete() 和ContentProvider.query()相同的selection 和selectionArgs参数。这可能使你能在这些方法之间重用代码。
Android 系统在启动provider后调用onCreate() 。你应该在此方法中只执行不耗时的初始化任务,并且推迟数据库创建和数据加载工作,直到provider直正收到对数据的请求时再做。如果你在onCreate()中做了耗时的工作,你将减慢provider的启动。相应的,这也会减缓从provider到其它应用的反应速度。
例如,如果你正在使用一个SQLite 数据库,你可以在ContentProvider.onCreate()中创建一个新的SQLiteOpenHelper 对象,然后在第一次打开数据库时创建SQL的表们。为了帮助你这样做,第一次调用getWritableDatabase()时,它会自动调用SQLiteOpenHelper.onCreate()方法。
下面的两个代码片段演示了在ContentProvider.onCreate() 和SQLiteOpenHelper.onCreate()之间的互动。第一段对ContentProvider.onCreate()的实现:
public class ExampleProvider extends ContentProvider /* * Defines a handle to the database helper object. The MainDatabaseHelper class is defined * in a following snippet. */ private MainDatabaseHelper mOpenHelper; // Defines the database name private static final String DBNAME = "mydb"; // Holds the database object private SQLiteDatabase db; public boolean onCreate() { /* * Creates a new helper object. This method always returns quickly. * Notice that the database itself isn't created or opened * until SQLiteOpenHelper.getWritableDatabase is called */ mOpenHelper = new SQLiteOpenHelper( getContext(), // the application context DBNAME, // the name of the database) null, // uses the default SQLite cursor 1 // the version number ); return true; } ... // Implements the provider's insert method public Cursor insert(Uri uri, ContentValues values) { // Insert code here to determine which table to open, handle error-checking, and so forth ... /* * Gets a writeable database. This will trigger its creation if it doesn't already exist. * */ db = mOpenHelper.getWritableDatabase(); } }
第二段代码是对SQLiteOpenHelper.onCreate()的实现,包含了一个helper类:
... // A string that defines the SQL statement for creating a table private static final String SQL_CREATE_MAIN = "CREATE TABLE " + "main " + // Table's name "(" + // The columns in the table " _ID INTEGER PRIMARY KEY, " + " WORD TEXT" " FREQUENCY INTEGER " + " LOCALE TEXT )"; ... /** * Helper class that actually creates and manages the provider's underlying data repository. */ protected static final class MainDatabaseHelper extends SQLiteOpenHelper { /* * Instantiates an open helper for the provider's SQLite data repository * Do not do database creation and upgrade here. */ MainDatabaseHelper(Context context) { super(context, DBNAME, null, 1); } /* * Creates the data repository. This is called when the provider attempts to open the * repository and SQLite reports that it doesn't exist. */ public void onCreate(SQLiteDatabase db) { // Creates the main table db.execSQL(SQL_CREATE_MAIN); } }
欢迎大家加入android技术交流QQ群:209796692