您的位置:首页 > 数据库

ContentProvider中的数据库的生成时机以及ContentResolver的insert()方法总结

2015-09-09 22:48 609 查看
  经过几天的总结,以及结合一些代码的实际测试,终于算是明白了ContentProvider中的数据的生成时机了。

目录结构:





MainActivity.java

package com.wyl.contentprovidermine2;

import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity implements OnClickListener{
Button btn_insert;
Button btn_select;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
System.out.println("MainActivity.onCreate().....1");
btn_insert = (Button) findViewById(R.id.btn_insert);
btn_select = (Button) findViewById(R.id.btn_select);
System.out.println("MainActivity.onCreate().....2");
btn_insert.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_insert:
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
values.put(MyMetaData.MyTableData.COLUMN_NAME, "wyl");
values.put(MyMetaData.MyTableData.COLUMN_SEX, "男");
//            values.put(MyMetaData.MyTableData.COLUMN_AGE, 24);
System.out.println("111 ==================");
if(cr!=null){
System.out.println("33333333333333");
cr.insert(MyMetaData.MyTableData.CONTENT_URI, values);
}
System.out.println("2222 ==================");
break;

case R.id.btn_select:
System.out.println("查询数据......");
break;
}
}
}


MyContentProvider.java

package com.wyl.contentprovidermine2;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;

public class MyContentProvider extends ContentProvider{
MySqliteHelper helper;
static{
System.out.println("我就是看看到底是先执行MyContentProvider.static{},");
}

public MyContentProvider(){
System.out.println("我是MyContentProvider()构造器,看看是否真的是自动实例化");
}

@Override
public boolean onCreate() {
System.out.println("MyContentProvider.onCreate()方法begins-----------");
helper = new MySqliteHelper(getContext(), "zhangyl.db");
System.out.println("下面开始真正建立数据库");
SQLiteDatabase db = helper.getWritableDatabase();//建数据库
System.out.println("MyContentProvider.onCreate()开始建表。。。。。。。。。。");
db.execSQL(MyMetaData.MyTableData.SQL_CREATE_TABLE);//建表
System.out.println("jianli le zhangyl.db");
return true;
}

@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// TODO Auto-generated method stub
return null;
}

@Override
public String getType(Uri uri) {
// TODO Auto-generated method stub
return null;
}

@Override
public Uri insert(Uri uri, ContentValues values) {
// TODO Auto-generated method stub
return null;
}

@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// TODO Auto-generated method stub
return 0;
}

@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
// TODO Auto-generated method stub
return 0;
}

}


MySqliteHelper.java

package com.wyl.contentprovidermine2;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;

public class MySqliteHelper extends SQLiteOpenHelper{

static{
System.out.println("我是MySqliteHelper.static{},");
}

public MySqliteHelper(Context context, String name, CursorFactory factory,
int version) {
super(context, name, factory, version);
}
public MySqliteHelper(Context context, String name,
int version) {
this(context, name,null, version);
}
/**
* 用来创建数据库
* @param context  activity
* @param name          数据库名
*/
public MySqliteHelper(Context context, String name) {
this(context, name, 1);
System.out.println("MySqliteHelper()构造器,我是来市里花的。");
}

/**
*  这个方法主要是用来创建 表的,
*  现在的疑问是 数据库是是什么时候创建的:实际上数据库是实例化该MySqliteHelper的时候
*  创建,
*/
@Override
public void onCreate(SQLiteDatabase db) {
//        db = getWritableDatabase();

System.out.println("MySqliteHelper.onCreate()方法,这里建表");
db.execSQL(MyMetaData.MyTableData.SQL_CREATE_TABLE);
System.out.println("MySqliteHelper.onCreate()方法,表已经建立好");
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

}

}


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

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.wyl.contentprovidermine2"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="19" />

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.wyl.contentprovidermine2.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<provider
android:name=".MyContentProvider"
android:authorities="com.wyl.contentprovidermine2" >
</provider>
</application>

</manifest>


activity_main.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.wyl.contentprovidermine.MainActivity"
tools:ignore="MergeRootFrame" >

<Button
android:id="@+id/btn_insert"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="insert data" >
</Button>

<Button
android:id="@+id/btn_select"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="select data" >
</Button>

</LinearLayout>




总结:

含有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行的代码

cr.insert(MyMetaData.MyTableData.CONTENT_URI, values);


调用的是MyContentProvider.java 的insert()方法,即

ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
values.put(myMetaData.UserTableMetaData.NAME, "zyl");
values.put(myMetaData.UserTableMetaData.AGE, 21);
values.put(myMetaData.UserTableMetaData.SEX, "女");
System.out.println("点了insert按钮......");
cr.insert(myMetaData.UserTableMetaData.CONTENT_URI, values);//实际上调用的是myContentProvider.insert()方法


contentResolver.insert()执行的时候,是通过调用 ContentProvider.insert()方法来实现插入数据的。因此生成数据库的时机也可以在ContentProvider的onCreate()方法里获取SqliteDataBase,下面的例子是ContentProvider的onCreate()方法,例如:

@Override
public Uri insert(Uri uri, ContentValues values) {
System.out.println("myContentProvider.insert()......1 ");
db = helper.getWritableDatabase();//在myContentProvider.insert()的方法里真正生成数据库
System.out.println("myContentProvider.insert()......2 ");
long rowId = db.insert(myMetaData.UserTableMetaData.TABLE_NAME, null, values);
if(rowId>0){
Uri rtnUri = ContentUris.withAppendedId(uri, rowId);
System.out.println("myContentProvider.insert()......3 ");
return rtnUri;
}
System.out.println("myContentProvider.insert()......4 ");
return null;
}


补充的内容里的代码放在文件管理里,名称:ContentProviderMine3.rar。

LogCat里的sysout如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: