ContentProvider中的数据生成时机
目录结构:
,
先给个结论:
仅仅是实例化mySqliteHelper()这个类的时候是不会创建数据库的,实际上数据库的真正创建是在helper.getWritableDatabase()的方法执行后才会真正创建,或者执行helper.getReadableDatabase()也会创建数据库(如果没有数据库的话)
安卓好这个应用控制台的System.out.print()的所有输出内容为:
09-09 05:30:28.892: I/System.out(2764): myContentProvider.static{} 静态代码块。。。。
09-09 05:30:28.904: I/System.out(2764): ==看看实例化本类的时候,是否会执行到我.....==
09-09 05:30:28.912: I/System.out(2764): helper实际上已经实例化了。。。
09-09 05:30:29.096: I/System.out(2764): mySqliteHelper onCreate(SQLiteDatabase db)方法......
09-09 05:30:29.144: I/System.out(2764): myContentProvider.onCreate()方法,实际上应该已经创建了数据库
09-09 05:30:29.144: I/System.out(2764): myContentProvider.onCreate()方法, jianli le zhangyalan.db
MainActivity.java
1 package com.wyl.contentprovidermine; 2 3 4 import android.app.Activity; 5 import android.content.ContentResolver; 6 import android.content.ContentValues; 7 import android.os.Bundle; 8 import android.view.View; 9 import android.view.View.OnClickListener; 10 import android.widget.Button; 11 public class MainActivity extends Activity implements OnClickListener{ 12 Button btn_insert; 13 Button btn_select; 14 @Override 15 protected void onCreate(Bundle savedInstanceState) { 16 super.onCreate(savedInstanceState); 17 setContentView(R.layout.activity_main); 18 btn_insert = (Button) findViewById(R.id.btn_insert); 19 btn_select = (Button) findViewById(R.id.btn_select); 20 btn_insert.setOnClickListener(this); 21 } 22 @Override 23 public void onClick(View v) { 24 switch (v.getId()) { 25 case R.id.btn_insert: 26 ContentResolver cr = getContentResolver(); 27 ContentValues values = new ContentValues(); 28 values.put(myMetaData.UserTableMetaData.NAME, "zyl"); 29 values.put(myMetaData.UserTableMetaData.AGE, 21); 30 values.put(myMetaData.UserTableMetaData.SEX, "女"); 31 // Uri uri = new URI() 32 System.out.println("点了insert按钮......"); 33 cr.insert(myMetaData.UserTableMetaData.CONTENT_URI, values); 34 System.out.println("点了insert按钮------------------"); 35 break; 36 37 case R.id.btn_select: 38 System.out.println("查询数据......"); 39 break; 40 } 41 } 42 }
myContentProvider.java
1 package com.wyl.contentprovidermine; 2 3 import android.content.ContentProvider; 4 import android.content.ContentUris; 5 import android.content.ContentValues; 6 import android.content.UriMatcher; 7 import android.database.Cursor; 8 import android.database.sqlite.SQLiteDatabase; 9 import android.net.Uri; 10 11 public class myContentProvider extends ContentProvider { 12 mySqliteHelper helper; 13 SQLiteDatabase db; 14 private static final UriMatcher myUriMatcher = new UriMatcher( 15 UriMatcher.NO_MATCH); 16 public static final int USERS = 1;// 代表表名 17 public static final int USERS_NAME = 2; // 字段名 18 public static final int USERS_SEX = 3; // 字段名 ,性别 19 public static final int USERS_AGE = 4; // 字段名,年龄 20 public static final int USERS_SINGLE = 5; 21 static { 22 System.out.println("myContentProvider.static{} 静态代码块。。。。"); 23 myUriMatcher.addURI(myMetaData.AUTHORITY, "/users", USERS);// 匹配表名 24 myUriMatcher.addURI(myMetaData.AUTHORITY, "/users/name", USERS_NAME); 25 myUriMatcher.addURI(myMetaData.AUTHORITY, "/users/sex", USERS_SEX); 26 myUriMatcher.addURI(myMetaData.AUTHORITY, "/users/age", USERS_AGE);// 只能匹配age这个字段 27 myUriMatcher.addURI(myMetaData.AUTHORITY, "/users/#", USERS_SINGLE);// 这个可以匹配任何字段名 28 } 29 30 @Override 31 public boolean onCreate() { 32 // TODO Auto-generated method stub 33 /* 34 * 创建数据库,同时也会生成表,见mySqliteHelper的onCreate()方法, 这个方法里有创建表的代码 35 */ 36 /* 37 * 如果这行代码(helper = new mySqliteHelper(getContext(),"zhangyalan.db");)注释掉了,那么当 38 * 插入数据的时候执行下面的insert方法的时候就会空指针异常,因为在清单文件中配置了,所以这个android app 39 * 安装的时候,就会执行这个类,即 myContentProvider.java ,而且 在这个类里,首先执行静态代码块里的代码, 40 * 然后执行本方法myContentProvider.onCreate(),本类的其他方法,如insert(),query()等方法,只 41 * 有用户在手机界面进行操作的时候才会执行到。知道了这里的执行顺序那么就很容易理解为什么下面的这行代码注释掉了就会 42 * 导致用户插入数据的时候会导致空指针异常了(因为 helper没有实例化),自己写一个ContentProvider的时候要首 43 * 先实例化这里就提示了我们很重要的一点,即实例化SQLiteOpenHelper的时机一定要早,比如放到静态代码块 44 * 或者onCreate()方法里 45 */ 46 helper = new mySqliteHelper(getContext(), "zhangyalan.db");// 这行代码千万要实例化 47 if (helper == null) { 48 System.out.println("helper实际上还没实例化"); 49 } else { 50 System.out.println("helper实际上已经实例化了。。。"); 51 } 52 helper.getWritableDatabase(); 53 System.out.println("myContentProvider.onCreate()方法,实际上应该已经创建了数据库"); 54 System.out 55 .println("myContentProvider.onCreate()方法, jianli le zhangyalan.db"); 56 return true; 57 } 58 59 @Override 60 public Cursor query(Uri uri, String[] projection, String selection, 61 String[] selectionArgs, String sortOrder) { 62 // TODO Auto-generated method stub 63 return null; 64 } 65 66 // 作用:根据传入的URI,返回该URI所表示的数据类型 67 @Override 68 public String getType(Uri uri) { 69 // TODO Auto-generated method stub 70 System.out.println("public String getType(Uri uri) 开始了。。。。。。"); 71 switch (myUriMatcher.match(uri)) { 72 case USERS: 73 return myMetaData.UserTableMetaData.CONTENT_TYPE; 74 75 case USERS_SINGLE: 76 return myMetaData.UserTableMetaData.CONTENT_TYPE_ITEM; 77 default: 78 throw new IllegalArgumentException("未知的uri,unknow URI..." + uri); 79 } 80 } 81 82 @Override 83 public Uri insert(Uri uri, ContentValues values) { 84 System.out.println("myContentProvider.insert()......1 "); 85 /* 86 * 仅仅是实例化mySqliteHelper()这个类的时候是不会创建数据库的 87 * 实际上数据库的真正创建是在helper.getWritableDatabase()的方法执行后才会真正创建, 88 * 或者执行helper.getReadableDatabase()也会创建数据库(如果没有数据库的话) 89 */ 90 db = helper.getWritableDatabase(); 91 System.out.println("myContentProvider.insert()......2 "); 92 long rowId = db.insert(myMetaData.UserTableMetaData.TABLE_NAME, null, 93 values); 94 if (rowId > 0) { 95 Uri rtnUri = ContentUris.withAppendedId(uri, rowId); 96 System.out.println("myContentProvider.insert()......3 "); 97 return rtnUri; 98 } 99 System.out.println("myContentProvider.insert()......4 "); 100 return null; 101 } 102 103 @Override 104 public int delete(Uri uri, String selection, String[] selectionArgs) { 105 // TODO Auto-generated method stub 106 return 0; 107 } 108 109 @Override 110 public int update(Uri uri, ContentValues values, String selection, 111 String[] selectionArgs) { 112 // TODO Auto-generated method stub 113 return 0; 114 } 115 116 }
mySqliteHelper.java
1 package com.wyl.contentprovidermine; 2 3 import android.content.Context; 4 import android.database.sqlite.SQLiteDatabase; 5 import android.database.sqlite.SQLiteDatabase.CursorFactory; 6 import android.database.sqlite.SQLiteOpenHelper; 7 8 public class mySqliteHelper extends SQLiteOpenHelper { 9 10 static { 11 12 System.out.println("==看看实例化本类的时候,是否会执行到我.....=="); 13 } 14 15 public mySqliteHelper(Context context, String name, CursorFactory factory, 16 int version) { 17 super(context, name, factory, version); 18 // TODO Auto-generated constructor stub 19 } 20 21 public mySqliteHelper(Context context, String name, int version) { 22 super(context, name, null, version); 23 // TODO Auto-generated constructor stub 24 } 25 26 /** 27 * 两个参数的构造器,用来创建数据库 28 * 29 * @param context 30 * activity 31 * @param name 32 * 数据库名 33 */ 34 public mySqliteHelper(Context context, String name) { 35 this(context, name, 1); 36 // TODO Auto-generated constructor stub 37 } 38 39 /** 40 * 这个方法主要是用来创建 表的, 现在的疑问是 数据库是是什么时候创建的:实际上数据库是实例化该MySqliteHelper的时候 41 * 并没有创建数据库,数据库的真正创建是在helper.getWritableDatabase()的方法执 42 * 行后才会真正创建,或者执行helper.getReadableDatabase()也会创建数据库(如果没有数据库的话) 43 */ 44 @Override 45 public void onCreate(SQLiteDatabase db) { 46 // TODO Auto-generated method stub 47 System.out 48 .println("mySqliteHelper onCreate(SQLiteDatabase db)方法......"); 49 db.execSQL(myMetaData.UserTableMetaData.CREATE_TABLE_SQL);// 创建表 50 } 51 52 @Override 53 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 54 // TODO Auto-generated method stub 55 56 } 57 58 }
myMetaData.java
1 package com.wyl.contentprovidermine; 2 3 import android.net.Uri; 4 import android.provider.BaseColumns; 5 6 public class myMetaData { 7 //AUTHORITY 是一个类名,即contentprovider的类名 8 public static final String AUTHORITY = "com.wyl.contentprovidermine"; 9 //数据库名称 10 public static final String DATABASE_NAME = "wyl.db"; 11 //表名 12 public static final String USER_TABLE_NAME = "users"; 13 14 public static class UserTableMetaData implements BaseColumns{ 15 //字表名称 16 public static final String TABLE_NAME = "users"; 17 18 public static final Uri CONTENT_URI = Uri.parse("content://"+AUTHORITY+"/users"); 19 //1 content 2 AUTHORITY 3.字标的名字 20 public static final String NAME = "name"; 21 public static final String SEX = "sex"; 22 public static final String AGE = "age"; 23 24 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.myprovider.users"; 25 //上面的 CONTENT_TYPE: 其中的 vnd.android.cursor.dir/vnd 是固定的, 后面的 myprovider.users 自己随便定义 26 public static final String CONTENT_TYPE_ITEM = "vnd.android.cursor.item/vnd.myprovider.users"; 27 28 public static final String DEFAULT_SORT_ORDER = "_id desc"; 29 30 public static final String CREATE_TABLE_SQL = "create table if not exists "+TABLE_NAME + " (_id integer primary key autoincrement,name text not null,sex text,age integer not null) "; 31 } 32 33 34 }