ContentProvider中的数据库的生成时机以及ContentResolver的insert()方法总结
经过几天的总结,以及结合一些代码的实际测试,终于算是明白了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()方法总结的更多相关文章
- 用C#从数据库动态生成AdminLTE菜单的一种方法
当前的应用设计风格趋于Flat扁平化,很多基于BootStrap实现了很多UI非常漂亮的管理界面(Bootstrap admin template). 此核心文件开源在Github:https://g ...
- springboot 中根据数据库表生成所有表的model,mapper和xml文件
参考文件:https://blog.csdn.net/shenmoren6/article/details/80337662?utm_source=blogxgwz1 详细信息:https://blo ...
- Delphi中根据分类数据生成树形结构的最优方法
一. 引言: TreeView控件适合于表示具有多层次关系的数据.它以简洁的界面,表现形式清晰.形象,操作简单而深受用户喜爱.而且用它可以实现ListView.ListBox所无法实现的很多功能 ...
- ContentProvider中的数据生成时机
目录结构: , 先给个结论: 仅仅是实例化mySqliteHelper()这个类的时候是不会创建数据库的,实际上数据库的真正创建是在helper.getWritableDatabase()的方法执行后 ...
- 在MVC3中使用code first生成数据局库并操作数据库
1.建立Users和UserInfos两个实体类 对应的是数据库中的表 public class User { //类名+Id(User+Id)组成的字符串在数据库表中会设置该字段是主键且是按1的增量 ...
- EF Core 2.0中怎么用DB First通过数据库来生成实体
要在EF Core使用DB First首先要下载三个Nuget包,在Nuget的Package Manager Console窗口中依次敲入下面三个命令即可: Microsoft.EntityFram ...
- (3)PyCharm中Flask工程逆向生成数据库表
一.创建数据库 在mysql数据库中创建名为"movie"的数据库. 二.安装SQLAlchemy 三.安装PyMySQL 四.创建数据模型 在app/models.py中编写数据 ...
- eclipse中从数据库生成hibernate实体类
为什么写这篇BLOG,是因为经常有同事或网友问起我hiberante实体类的生成问题.所以下次再有人问我可以省一堆的话了,其实这个真的是很简单. 现在hibernate在项目中的应用是越 ...
- SQL C# nvarchar类型转换为int类型 多表查询的问题,查询结果到新表,TXT数据读取到控件和数据库,生成在控件中的数据如何存到TXT文件中
在数据库时候我设计了学生的分数为nvarchar(50),是为了在从TXT文件中读取数据插入到数据库表时候方便,但是在后期由于涉及到统计问题,比如求平均值等,需要int类型才可以,方法是:Conver ...
随机推荐
- 在InteliJ IDEA中写Dart及配置IDEA - Dart Plugin
此文运用的是优雅的Markdown而书 Dart官方建议使用的编译器是DartEditor,我下载下来看下,和Eclipse的界面很相像.对于Eclipse,我是既爱又恨,爱它的稳定,恨它的功能没有I ...
- oracle如何修改字段类型(oracle总体知识2)
在一次做开发的时候,遇到需要将数据表的字段类型由number改成varchar,可是该字段又有值, 用 alter table t-name modify cname newType;会报错. 话说 ...
- 文件的哈希值不在指定的目录文件中。此文件可能已损坏或被篡(Windows10 /Windows8.1)
------------------------------------------Windows10------------------------------------------------ ...
- NHibernate 的 ID 标识选择器
在 Hibernate 中,每个对象需要一个标识 ID,通过这个标识 ID 建立对象与数据库中记录的对应关系. Nhibernate 提供了多种方式来建立这个 POID.基于不同的生成策略,可以选择更 ...
- TableLayoutPanel 的使用
VS自带控件TableLayoutPanel的功能应用网上都有资料.下面是使用中的一些问题. 1.动态加载控件时使用SetRowSpan.SetColumnSpan方法会使得界面响应缓慢 解决方案: ...
- 一道月薪3W的java面试题 (小明和小强都是张老师的学生,张老师的生日是某月某日,2人都不知道张老师的生日)
小明和小强都是张老师的学生,张老师的生日是M月N日,2人都知道张老师的生日 是下列10组中的一天,张老师把M值告诉了小明,把N值告诉了小强,张老师问他们知道他的生日是那一天吗? 3月4日 3月5日 3 ...
- C语言数据结构----双向链表
概括:主要说明双向链表的基本概念和具体操作以及源代码. 一.基本概念 1.有了单链表以后我们可以把内存中小块的空间联系在一起,并且把每一个小块都存储上我们想要存储的数值.但是单链表只有一个next,我 ...
- Android调用系统关机与重启功能
我是在android源码里编译的package/apps/,因为需要调用的关机接口是不对上层开放的,在eclipse里面不能调用. 我主要是介绍调用android的关机功能,因为在调试过程中,关机的一 ...
- Ext JS学习第十天 Ext基础之 扩展原生的javascript对象(二)
此文来记录学习笔记: 今天继续说Ext.Array,Ext.Function,Ext.Date,Ext.Error ------------------------------------------ ...
- iOS开发中遇到的bug
报错:The operation couldn’t be completed. (LaunchServicesError error 0.) 解决办法:重置模拟器