好记性不如烂笔杆-android学习笔记<九> Content Provider 数据共享机制
21,//Content Provider 数据共享机制
<1>//在minifest.xml文件中注册
<provider
android:name="zjq.contentprovider.FirstContentProvider"
android:authorities="zjq.contentprovider.FirstContentProvider"
/>
//main.xml文件中添加一个TextView和两个Button
Java文件
<2>//创建一个数据库的工具类
1 public class FirstProviderMetaData { 2 public static final String AUTHORIY = "zjq.contentprovider.FirstContentProvider"; 3 //数据库名称 4 public static final String DATABASE_NAME = "FirstProvider.db"; 5 //数据库版本 6 public static final int DATABASE_VERSION = 1; 7 //表名 8 public static final String USERS_TABLE_NAME = "users"; 9 10 public static final class UserTableMetaData implements BaseColumns{ 11 //表名 12 public static final String TABLE_NAME = "users"; 13 //访问该ContentProvider的URL 14 public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORIY + "/users"); 15 //访问该ContentProvider所返回的数据类型的定义 16 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.firstprovider.user"; 17 public static final String CONTENT_TYPE_ITEM = "vnd.android.cursor.item/vnd.firstprovider.user"; 18 //列名 19 public static final String USER_NAME = "name"; 20 //默认的排序方法 21 public static final String DEFAULT_SORT_ORDER = "_id desc"; 22 } 23 }
<3>//创建一个数据库
//DatabaseHelper作为一个访问SQLite的助手类,提供两个方面的功能
//第一,getReadableDatabase(),getWritableDatabase()可以获得SQLiteDatabase对象,通过该对象可以对数据库进行操作
//第二,提供了onCreate和onUpgrade两个回调函数,允许我们创建和升级数据库时,进行自己的操作。
1 public class DatabaseHelper extends SQLiteOpenHelper { 2 private static final int VERSION = 1 ; 3 //在SQLiteOpenHelper的子类中,必须有该构造函数 4 public DatabaseHelper(Context context, String name, CursorFactory factory, 5 int version){ 6 //必须通过super调用父类当中的构造函数 7 super(context, name, factory, version); 8 } 9 public DatabaseHelper(Context context, String name){ 10 //必须通过super调用父类当中的构造函数 11 this(context, name,VERSION); 12 } 13 public DatabaseHelper(Context context, String name,int version){ 14 //必须通过super调用父类当中的构造函数 15 this(context, name,null, version); 16 } 17 18 //该函数是在第一次创建数据库的时候执行,实际上是在第一次得到SQLiteDatabase对象的时候,才会调用这个方法 19 @Override 20 public void onCreate(SQLiteDatabase db) { 21 System.out.println("create a Database"); 22 //execSQL函数用于执行SQL语句 23 db.execSQL("create table " + FirstProviderMetaData.USERS_TABLE_NAME 24 + "(" + FirstProviderMetaData.UserTableMetaData._ID 25 + " INTEGER PRIMARY KEY AUTOINCREMENT," 26 + FirstProviderMetaData.UserTableMetaData.USER_NAME 27 + " varchar(20))"); 28 } 29 @Override 30 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 31 // TODO Auto-generated method stub 32 System.out.println("update a Database"); 33 } 34 }
<4>//创建一个ContentProvider对象,对数据库的接口进行包装:
1 public class FirstContentProvider extends ContentProvider { 2 3 public static final UriMatcher uriMatcher; 4 public static final int INCOMING_USER_COLLECTION = 1; 5 public static final int INCOMING_USER_SINGLE = 2; 6 private DatabaseHelper dh; 7 static { 8 //UriMatcher 在ContentProvider中帮助匹配URL 9 uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 10 //FirstProviderMetaData.AUTHORIY部分的值是之前URL中/和/之间的内容,所以这里不需要users前的/ 11 uriMatcher.addURI( FirstProviderMetaData.AUTHORIY, "users", 12 INCOMING_USER_COLLECTION); 13 uriMatcher.addURI(FirstProviderMetaData.AUTHORIY, "users/#", 14 INCOMING_USER_SINGLE); 15 } 16 public static HashMap<String,String> userProjectionMap; 17 static 18 { 19 userProjectionMap = new HashMap<String,String>(); 20 userProjectionMap.put(UserTableMetaData._ID,UserTableMetaData._ID); 21 userProjectionMap.put(UserTableMetaData.USER_NAME, UserTableMetaData.USER_NAME); 22 } 23 @Override 24 public int delete(Uri arg0, String arg1, String[] arg2) { 25 System.out.println("delete"); 26 return 0; 27 } 28 29 //根据传入的URI,返回该URI所表示的数据类型 30 @Override 31 public String getType(Uri uri) { 32 System.out.println("getType"); 33 switch(uriMatcher.match(uri)){ 34 case INCOMING_USER_COLLECTION: 35 return UserTableMetaData.CONTENT_TYPE; 36 case INCOMING_USER_SINGLE: 37 return UserTableMetaData.CONTENT_TYPE_ITEM; 38 default: 39 throw new IllegalArgumentException("Unknown URI" + uri); 40 } 41 } 42 /** 43 * 该函数的返回值是一个URI,这个URI表示的是刚刚使用这个函数所插入的数据 44 * content://mars.cp.FirstContentProvider/users/1 45 */ 46 @Override 47 public Uri insert(Uri uri, ContentValues values) { 48 System.out.println("insert"); 49 SQLiteDatabase db = dh.getWritableDatabase(); 50 long rowId = db.insert(UserTableMetaData.TABLE_NAME, null, values); 51 if(rowId > 0){ 52 Uri insertedUserUri = ContentUris.withAppendedId(UserTableMetaData.CONTENT_URI, rowId); 53 //通知监听器,数据已经改变 54 getContext().getContentResolver().notifyChange(insertedUserUri, null); 55 return insertedUserUri; 56 } 57 throw new SQLException("Failed to insert row into" + uri); 58 } 59 60 //是一个回调方法,所以说在ContentProvider创建的时候执行 61 @Override 62 public boolean onCreate() { 63 //打开数据库 64 dh = new DatabaseHelper(getContext(),FirstProviderMetaData.DATABASE_NAME); 65 System.out.println("FirstContentProvider.java onCreate"); 66 return true; 67 } 68 //查询方法 69 @Override 70 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 71 String sortOrder) { 72 System.out.println("Query Debug"); 73 //SQLiteQueryBuilder类,用于创建一个查询的语句 74 SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 75 int type = uriMatcher.match(uri); 76 switch(type){ 77 case INCOMING_USER_COLLECTION: 78 qb.setTables(UserTableMetaData.TABLE_NAME); 79 qb.setProjectionMap(userProjectionMap); 80 break; 81 case INCOMING_USER_SINGLE: 82 qb.setTables(UserTableMetaData.TABLE_NAME); 83 qb.setProjectionMap(userProjectionMap); 84 qb.appendWhere(UserTableMetaData._ID + "=" + uri.getPathSegments().get(1)); 85 break; 86 } 87 String orderBy; 88 if(TextUtils.isEmpty(sortOrder)){ 89 orderBy = UserTableMetaData.DEFAULT_SORT_ORDER; 90 } 91 else{ 92 orderBy = sortOrder; 93 } 94 SQLiteDatabase db = dh.getWritableDatabase(); 95 Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy); 96 c.setNotificationUri(getContext().getContentResolver(), uri); 97 System.out.println("query"); 98 return c; 99 } 100 @Override 101 public int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3) { 102 System.out.println("update"); 103 return 0; 104 } 105 }
<5>//创建一个测试用的Activity,对DB进行插入和查找
1 public class CPActivity extends Activity { 2 private Button insertButton = null; 3 private Button queryButton = null; 4 @Override 5 public void onCreate(Bundle savedInstanceState) { 6 super.onCreate(savedInstanceState); 7 setContentView(R.layout.main); 8 queryButton = (Button) findViewById(R.id.query); 9 queryButton.setOnClickListener(new QueryListener()); 10 insertButton = (Button) findViewById(R.id.insert); 11 insertButton.setOnClickListener(new InsertListener()); 12 System.out.println(getContentResolver().getType(FirstProviderMetaData.UserTableMetaData.CONTENT_URI)); 13 } 14 class InsertListener implements OnClickListener { 15 16 @Override 17 public void onClick(View v) { 18 ContentValues values = new ContentValues(); 19 //把数据存如Values中 20 values.put(FirstProviderMetaData.UserTableMetaData.USER_NAME, 21 "zhangsan"); 22 Uri uri = getContentResolver() 23 .insert( 24 FirstProviderMetaData.UserTableMetaData.CONTENT_URI, 25 values); 26 System.out.println("uri--->" + uri.toString()); 27 } 28 29 } 30 class QueryListener implements OnClickListener { 31 32 @Override 33 public void onClick(View v) { 34 //设置查询表中的那些字段,new String[]{"_id","name"} 35 Cursor c = getContentResolver().query( 36 FirstProviderMetaData.UserTableMetaData.CONTENT_URI, new String[]{"_id","name"}, 37 null, null, null); 38 while(c.moveToNext()){ 39 //System.out.println(c.getString(c.getColumnIndex(UserTableMetaData.USER_NAME))); 40 } 41 } 42 } 43 }
<6>,其他的一些指令
1 //删除数据库: 2 3 Context.deleteDatabase(String name)删除指定名称的数据库 4 this.deleteDatabase("myDatabase.db"); 5 //打开数据库: 6 SQLiteDatabase my_DataBase = this.openOrCreateDatabase("myDatabase.db",MODE_PRIVATE,null); 7 my_Database.close(); 8 //非查询 SQL 指令 9 SQLiteDatabase.execSQL(String sql)可以用来执行非查询 SQL 指令,这些指令没有结果 10 包括:CREATE TABLE / DROP TABLE / INSERT 等等 11 //创建一个名为"test"并带两个参数的表 12 my_DataBase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, 13 someNumber INTERGER);"); 14 //在数据库中插入一个元组 15 my_DataBase.execSQL("INSERT INTO test (_id,someNumber) values(1,8);"); 16 //删除表 17 my_DataBase.execSQL("DROP TABLE test");