经过几天的总结,以及结合一些代码的实际测试,终于算是明白了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. RAW模板命名规范

    国有国法,家有家规,任何一种开发都要有自己规范,RAW模板也一样,这个文章来介绍一下RAW模板命名的规范. 格式: 开发者或组织_描述词_名称 开发者或组织:如know或自己的组织名 描述词:c-&g ...

  2. FPGA知识大梳理(四)FPGA中的复位系统大汇总

    本文整合特权(吴厚航)和coyoo(王敏志)两位大神的博文.我也很推崇这两位大神的书籍,特权的书籍要偏基础一下,大家不要一听我这么说就想买coyoo的.我还是那一句话,做技术就要step by ste ...

  3. C winpcap 网络抓包 并获取IP TCP 协议的相关信息

    以太网协议分析函数: void ethernet_protocol_packet_handle (u_char *argument, const struct pcap_pkthdr *packet_ ...

  4. IAR Embedded Workbench for ARM 6.50.6 & 6.60.1 破解补丁

    IAR EWARM 6.50.6 & 6.60.1 破解 破解原理和方法见:http://blog.csdn.net/chivalrys/article/details/8564568 IAR ...

  5. AES 加密

    package com.sprucetec.tms.utils; import java.security.Key; import javax.crypto.Cipher;import javax.c ...

  6. 链队列之C++实现

    链队列时建立在单链表的基础之上的.由于是动态分配节点内存,所以无需判满. 链队列的形式如下: 1.队列空 2.队列存在数据 下面介绍下C++实现的链队列,VC6下调试通过. 1.文件组织 2.lq.h ...

  7. C++模板:二分查找

    bool find(int x,int l,int r){ if(l>r)return false; int mid=(l+r)/2; if(s[mid]==x) return true; el ...

  8. APUE学习之------------信号

    在学习一个东西的时候我总是喜欢去问这样做的理由是什么?也喜欢去究竟他的历史.从中你可以发现所有的设计都在不断改进出来的,从来就没有一个设计是一开始就是完美的.好比是人,之初,性也许是善的,如果我们不通 ...

  9. JavaBean讲解 规范

    一:JavaBean定义 JavaBean是一种可重复使用.跨平台的软件组件.JavaBean可分为两种:一种是有用户界面(UI,User Interface)的JavaBean,例如NetBean中 ...

  10. [译]Stairway to Integration Services Level 16 – Flexible Source Locations (多文件导入)

    介绍 在本文中我们将利用SSIS参数,变量 以及 Foreach Loop Container 从多个源动态导入数据. 开始前我们先下载一些数据.WeatherData_Dec08_Apr09.zip ...