经过几天的总结,以及结合一些代码的实际测试,终于算是明白了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如下:

ContentProvider中的数据库的生成时机以及ContentResolver的insert()方法总结的更多相关文章

  1. 用C#从数据库动态生成AdminLTE菜单的一种方法

    当前的应用设计风格趋于Flat扁平化,很多基于BootStrap实现了很多UI非常漂亮的管理界面(Bootstrap admin template). 此核心文件开源在Github:https://g ...

  2. springboot 中根据数据库表生成所有表的model,mapper和xml文件

    参考文件:https://blog.csdn.net/shenmoren6/article/details/80337662?utm_source=blogxgwz1 详细信息:https://blo ...

  3. Delphi中根据分类数据生成树形结构的最优方法

    一. 引言:    TreeView控件适合于表示具有多层次关系的数据.它以简洁的界面,表现形式清晰.形象,操作简单而深受用户喜爱.而且用它可以实现ListView.ListBox所无法实现的很多功能 ...

  4. ContentProvider中的数据生成时机

    目录结构: , 先给个结论: 仅仅是实例化mySqliteHelper()这个类的时候是不会创建数据库的,实际上数据库的真正创建是在helper.getWritableDatabase()的方法执行后 ...

  5. 在MVC3中使用code first生成数据局库并操作数据库

    1.建立Users和UserInfos两个实体类 对应的是数据库中的表 public class User { //类名+Id(User+Id)组成的字符串在数据库表中会设置该字段是主键且是按1的增量 ...

  6. EF Core 2.0中怎么用DB First通过数据库来生成实体

    要在EF Core使用DB First首先要下载三个Nuget包,在Nuget的Package Manager Console窗口中依次敲入下面三个命令即可: Microsoft.EntityFram ...

  7. (3)PyCharm中Flask工程逆向生成数据库表

    一.创建数据库 在mysql数据库中创建名为"movie"的数据库. 二.安装SQLAlchemy 三.安装PyMySQL 四.创建数据模型 在app/models.py中编写数据 ...

  8. eclipse中从数据库生成hibernate实体类

    为什么写这篇BLOG,是因为经常有同事或网友问起我hiberante实体类的生成问题.所以下次再有人问我可以省一堆的话了,其实这个真的是很简单.        现在hibernate在项目中的应用是越 ...

  9. SQL C# nvarchar类型转换为int类型 多表查询的问题,查询结果到新表,TXT数据读取到控件和数据库,生成在控件中的数据如何存到TXT文件中

    在数据库时候我设计了学生的分数为nvarchar(50),是为了在从TXT文件中读取数据插入到数据库表时候方便,但是在后期由于涉及到统计问题,比如求平均值等,需要int类型才可以,方法是:Conver ...

随机推荐

  1. 5.7.1.3 Global 对象的属性

    Global对象还包含了一些属性,例如,特殊的值undefined.NaN以及Infinity都是Global对象的属性.此外,所有原生引用类型的构造函数,像Object和Function,也都是Gl ...

  2. 0610 python 基础03

    复习: 条件判断 if..else >>> age=28 >>> if age<18: ...   print "你还没有成年吧" ... ...

  3. PowerShell Remove all user defined variable in PowerShell

    When PS scripts executes, it is possibly create much user defined variables. So, sometimes these var ...

  4. ***EF中的问题(复习的同学可略过)

    1.当类中出现两个导航属性时,需使用额外代码说明类之间的关系. [ForeignKey("Id")] [InverseProperty("Id"]

  5. php命名空间及和autoload结合使用问题。

    在讨论如何使用命名空间之前,必须了解 PHP 是如何知道要使用哪一个命名空间中的元素的.可以将 PHP 命名空间与文件系统作一个简单的类比.在文件系统中访问一个文件有三种方式: 相对文件名形式如foo ...

  6. [转载]Android 知识图谱

    from: http://blog.csdn.net/xyz_lmn/article/details/41411355

  7. C语言参数传递

    //--------------------单向值传递------------------------ // swap这个方法在被调用时,给形参a,b分配了空间 // 主调函数将[数值]传递给[形参] ...

  8. VCS引起的oracle数据库异常重新启动一例

    1. 环境描写叙述 操作系统版本号:SUSE Linux Enterprise Server 10 sp2 (x86_64) 数据库版本号:Oracle 11.1.0.7.16 VCS版本号:5.1 ...

  9. TreeView控件绑定数据库

    1.在设计视图里面的代码 <form id="form1" runat="server"> <div> <h1>两个表< ...

  10. js 特效 手风琴效果

    $(document).ready(function(){ //定义展开的块 var lastBlock = $('#a1'); //展开的块的宽度 var maxWidth = 406; //折叠的 ...