经过几天的总结,以及结合一些代码的实际测试,终于算是明白了ContentProvider中的数据的生成时机了。
目录结构:
MainActivity.java
1 package com.wyl.contentprovidermine2; 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 @Override15 protected void onCreate(Bundle savedInstanceState) {16 super.onCreate(savedInstanceState);17 setContentView(R.layout.activity_main);18 System.out.println("MainActivity.onCreate().....1");19 btn_insert = (Button) findViewById(R.id.btn_insert);20 btn_select = (Button) findViewById(R.id.btn_select);21 System.out.println("MainActivity.onCreate().....2");22 btn_insert.setOnClickListener(this);23 }24 @Override25 public void onClick(View v) {26 switch (v.getId()) {27 case R.id.btn_insert:28 ContentResolver cr = getContentResolver();29 ContentValues values = new ContentValues();30 values.put(MyMetaData.MyTableData.COLUMN_NAME, "wyl");31 values.put(MyMetaData.MyTableData.COLUMN_SEX, "男");32 // values.put(MyMetaData.MyTableData.COLUMN_AGE, 24);33 System.out.println("111 ==================");34 if(cr!=null){35 System.out.println("33333333333333");36 cr.insert(MyMetaData.MyTableData.CONTENT_URI, values);37 }38 System.out.println("2222 ==================");39 break;40 41 case R.id.btn_select:42 System.out.println("查询数据......");43 break;44 }45 }46 }
MyContentProvider.java
1 package com.wyl.contentprovidermine2; 2 3 4 import android.content.ContentProvider; 5 import android.content.ContentValues; 6 import android.database.Cursor; 7 import android.database.sqlite.SQLiteDatabase; 8 import android.net.Uri; 9 10 public class MyContentProvider extends ContentProvider{11 MySqliteHelper helper;12 static{13 System.out.println("我就是看看到底是先执行MyContentProvider.static{},");14 }15 16 public MyContentProvider(){17 System.out.println("我是MyContentProvider()构造器,看看是否真的是自动实例化");18 }19 20 @Override21 public boolean onCreate() {22 System.out.println("MyContentProvider.onCreate()方法begins-----------");23 helper = new MySqliteHelper(getContext(), "zhangyl.db");24 System.out.println("下面开始真正建立数据库");25 SQLiteDatabase db = helper.getWritableDatabase();//建数据库26 System.out.println("MyContentProvider.onCreate()开始建表。。。。。。。。。。");27 db.execSQL(MyMetaData.MyTableData.SQL_CREATE_TABLE);//建表28 System.out.println("jianli le zhangyl.db");29 return true;30 }31 32 @Override33 public Cursor query(Uri uri, String[] projection, String selection,34 String[] selectionArgs, String sortOrder) {35 // TODO Auto-generated method stub36 return null;37 }38 39 @Override40 public String getType(Uri uri) {41 // TODO Auto-generated method stub42 return null;43 }44 45 @Override46 public Uri insert(Uri uri, ContentValues values) {47 // TODO Auto-generated method stub48 return null;49 }50 51 @Override52 public int delete(Uri uri, String selection, String[] selectionArgs) {53 // TODO Auto-generated method stub54 return 0;55 }56 57 @Override58 public int update(Uri uri, ContentValues values, String selection,59 String[] selectionArgs) {60 // TODO Auto-generated method stub61 return 0;62 }63 64 }
MySqliteHelper.java
1 package com.wyl.contentprovidermine2; 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 System.out.println("我是MySqliteHelper.static{},");12 }13 14 public MySqliteHelper(Context context, String name, CursorFactory factory,15 int version) {16 super(context, name, factory, version);17 }18 public MySqliteHelper(Context context, String name, 19 int version) {20 this(context, name,null, version);21 }22 /**23 * 用来创建数据库24 * @param context activity25 * @param name 数据库名26 */27 public MySqliteHelper(Context context, String name) {28 this(context, name, 1);29 System.out.println("MySqliteHelper()构造器,我是来市里花的。");30 }31 32 /**33 * 这个方法主要是用来创建 表的,34 * 现在的疑问是 数据库是是什么时候创建的:实际上数据库是实例化该MySqliteHelper的时候35 * 创建,36 */37 @Override38 public void onCreate(SQLiteDatabase db) {39 // db = getWritableDatabase();40 41 System.out.println("MySqliteHelper.onCreate()方法,这里建表");42 db.execSQL(MyMetaData.MyTableData.SQL_CREATE_TABLE);43 System.out.println("MySqliteHelper.onCreate()方法,表已经建立好");44 }45 46 @Override47 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {48 49 }50 51 }
MyMetaData.java
package com.wyl.contentprovidermine2;import android.net.Uri;import android.provider.BaseColumns;public class MyMetaData { public static final String AUTHORITY = "com.wyl.contentprovidermine2"; public static final class MyTableData implements BaseColumns{ // 1.相当于http 2.provider所在的包名 3.表名 public static final Uri CONTENT_URI = Uri.parse("content://"+AUTHORITY+"/yonghu"); public static final String TABLE_NAME = "yonghu"; public static final String COLUMN_NAME = "name"; public static final String COLUMN_SEX = "sex"; public static final String COLUMN_AGE = "age"; public static final String COLUMN_SORT = "_id desc"; //create table if not exists yonghu (_id integer primary key autoincrement,name text not null,sex text not null,age integer not null); public static final String SQL_CREATE_TABLE = "create table if not exists "+TABLE_NAME+" (_id integer primary key autoincrement,"+COLUMN_NAME+" text not null,"+COLUMN_SEX+" text not null, "+COLUMN_AGE+" integer not null)"; public static final String SQL_CREATE_TABLE2 = "create table if not exists "+TABLE_NAME+" (_id integer primary key autoincrement,"+COLUMN_NAME+" text not null,"+COLUMN_SEX+" text not null, "+COLUMN_AGE+" integer not null)"; }}
AndroidManifest.xml
1 26 7 10 11 16 19 20 24 25 2621 22 23 29 30 31 32
activity_main.xml:
19 10 15 16 17 22 23 24
总结:
含有ContentProvider
组件的app安装的时候的执行顺序,安装的时候,系统就会自动实例化继承了ContentProvider类的类(我这里使用的是MyContentProvider 这个类继承了ContentProvider),这一步是系统自动实例化(这是我的理解,用代码测试出的这个结论)实例化MyContentProvider,当然会遵循实例化的顺序,即a 先执行MyContentProvider内的static{},即静态代码块,b 然后{},即普通代码块,c 然后才生成MyContentProvider对象,即执行构造器内的代码d 这个时候才真正自动执行MyContentProvider里的onCreate()方法,结合本例子中的时机代码,执行上面onCreate()方法的整个过程中实际上又可以分为以下几个过程,具体如下,其中 1 对应着:实例化MySqliteHelper(),至于静态代码等的执行顺序类同于上面的abcd四个步骤。不细说。刚开始我以为实例化MySqliteHelper这个类的时候,就会建立数据库,其实不然。而是到了上图中的第二个步骤的时候才真正创建数据库,即调用了helper的getWritableDatabase()方法的时候才会真正创建数据库。实际上调用helper.getReadableDatabase()也同样会真正创建数据库。其中2对应着: 这个时候真正的创建数据库,1中已经讲了。
其中3对应着:真正创建表,这个很简单没必要讲。
20150910补充:
实际上上面MainActivity.java 36行的代码
1 cr.insert(MyMetaData.MyTableData.CONTENT_URI, values);
调用的是MyContentProvider.java 的insert()方法,即
1 ContentResolver cr = getContentResolver();2 ContentValues values = new ContentValues();3 values.put(myMetaData.UserTableMetaData.NAME, "zyl");4 values.put(myMetaData.UserTableMetaData.AGE, 21);5 values.put(myMetaData.UserTableMetaData.SEX, "女");6 System.out.println("点了insert按钮......");7 cr.insert(myMetaData.UserTableMetaData.CONTENT_URI, values);//实际上调用的是myContentProvider.insert()方法
contentResolver.insert()执行的时候,是通过调用 ContentProvider.insert()方法来实现插入数据的。因此生成数据库的时机也可以在ContentProvider的onCreate()方法里获取SqliteDataBase,下面的例子是ContentProvider的onCreate()方法,例如:
1 @Override 2 public Uri insert(Uri uri, ContentValues values) { 3 System.out.println("myContentProvider.insert()......1 "); 4 db = helper.getWritableDatabase();//在myContentProvider.insert()的方法里真正生成数据库 5 System.out.println("myContentProvider.insert()......2 "); 6 long rowId = db.insert(myMetaData.UserTableMetaData.TABLE_NAME, null, values); 7 if(rowId>0){ 8 Uri rtnUri = ContentUris.withAppendedId(uri, rowId); 9 System.out.println("myContentProvider.insert()......3 ");10 return rtnUri;11 }12 System.out.println("myContentProvider.insert()......4 ");13 return null;14 }
补充的内容里的代码放在文件管理里,名称:ContentProviderMine3.rar。
LogCat里的sysout如下: