contentprovider实例何时创建?SQLiteDatabase方法何时执行

&&国之画&&&& &&&&&&
&& &&&&&&&&&&&&&&
鲁ICP备号-4
打开技术之扣,分享程序人生!Android数据存储访问方式-SQLite,ContentProvider的应用
SQLite的简单介绍
SQLite是一个开源的,小型的嵌入式数据库,小而巧的特点特别适用于移动设备的开发中.
SQLite数据库的最大特点是"弱类型",即虽然在创建表的时候指定了列的数据类型,但在插入数据时不一定就使用指定了数据类型,当插入数据的数据类型与指定的不匹配,SQLite会尝试进行转换,如果不能转换则直接按本身类型存储.
另外,SQLite不支持一些标准SQL功能,如外键约束(foreign key),嵌套(transaction),右联接(right out join),全联接(full out join)
SQLiteOpenHelper
Android提供了SQLiteOpenHelper类,用于帮助管理数据库,例如创建或更新一个数据库(实际上是使用SQLiteDatabase的函数来执行sql语句).该类是抽象类,我们需要自己继承,重写onCreate()和onUpgrade()函数.一个简单的SQLiteOpenHelper继承类如下:
class DatabaseHelper extends SQLiteOpenHelper{
DatabaseHelper(Context ctx){
super(context, databasename, cursorFactory, databaseversion);
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table ............");
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("drop table is exists ...");
onCreate(db);
SQLiteOpenHelper中提供了两个函数来获得SQLiteDatabase对象,分别是getReadableDatabase()和getWritableDatabase()函数,这两个函数都是线程安全的,能返回可读/写的数据库对象,而它们的区别在于:
1.当存储空间(disk)满时,getReadableDatabase()会返回一个可读数据库对象,而getWritableDatabase()则会失败.知道存储空间满的问题被解决了.
2.假如现在已经有一个数据库对象存在并已经是打开状态,那getReadableDatabase()会返回这个已经存在的数据库对象,而对于getWritableDatabase()它还会判断该对象是read-only还是read/write的,如果是read/write的,则直接返回该数据库对象,如果是read-only的,则会把该数据库对象加锁,并尝试创建一个新的数据库对象,如果新的数据库对象创建成功,则返回新数据库对象,把旧数据库对象关闭、解锁、指向新数据库对象,如果创建失败则把旧数据库对象解锁.(详细看SQLiteOpenHelper类的源代码,这里只是初步看了下,并没验证,可能有错误或遗漏地方)
SQLiteDatabase
SQLiteDatabase提供了execSQL()函数用于执行原生sql语句,另外还提供了insert(),update(),delete(),query()等函数,通过重写实现我们的需求
后四种函数都把sql语句拆分作为参数传入,而在使用这些函数的过程中,我们又需要用到其他一些类,如Uri,UriMatcher,SQLiteQueryBuilder,ContentValues,ContentResolver,ContentUris,ContentProvider,Cursor等
Android的数据库操作形式类似于REST架构web的访问形式,Uri表示了我们要操作的目标
ContentProvider相当于封装类,把所有的事情都封装在其中,提供操作接口,这就使我们在更高一层来进行数据库操作了.
Cursor类似于JDBC中的ResultSet,表示返回的查询结果集(Cursor是一个接口,这里返回的应该是SQLiteCursor对象?)
Uri(android.net.Uri)
Android中使用了类似REST架构的形式来请求数据库(了解REST架构对于理解为什么Android用Uri很有帮助)
Uri是一个抽象类,我们使用它的静态方法parse()来创建一个Uri(StringUri)
Uri uri = Uri.parse("content://com.ksn.provider.BookProvider/books");
看下面两条uri的区别
content://com.ksn.provider.BookProvider/books/----------------代表了books表下所有记录
content://com.ksn.provider.BookProvider/books/13-------------代表了books表下id为13的记录
UriMatcher
UriMatcher用来解释Uri,识别Uri的类型,从而进行正确的操作.例如识别Uri是对一组数据还是一条数据进行操作.
为UriMatcher注册模式:
private static final UriMatcher sUriM
private static final int INCOME_BOOK_COLLECTION_URI_INDICATOR = 1;
private static final int INCOME_SINGLE_BOOK_URI_INDICATOR = 2;
sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
sUriMatcher.addURI(BookProviderMetaData.AUTHORITY, "books", INCOME_BOOK_COLLECTION_URI_INDICATOR);
sUriMatcher.addURI(BookProviderMetaData.AUTHORITY, "books/#", INCOME_SINGLE_BOOK_URI_INDICATOR);
/*然后就可以使用match(uri)来识别改uri属于哪种模式了.*/
public String getType(Uri uri) {
switch(sUriMatcher.match(uri)){
case INCOME_BOOK_COLLECTION_URI_INDICATOR:
return BookTableMetaData.CONTENT_TYPE;
case INCOME_SINGLE_BOOK_URI_INDICATOR:
return BookTableMetaData.CONTENT_ITEM_TYPE;
throw new IllegalArgumentException("Unknown URI " + uri);
Cursor
使用游标须注意:
-游标是一个行集合
-游标默认并不是指向第一条记录,所以在使用前先调用moveToFirst()
-需要知道列名
-需要知道列类型
-所有字段的访问都是基于列编号的,所以必须先讲列名转换为列编号
-游标可以随意移动
-游标可以用来获取行数
ContentProvider
作为上层的封装类,ContentProvider提供了基本CRUD函数,由我们来重写
-public abstract Cursor query(Uri uri, String[] projection,String selection, String[] selectionArgs, String sortOrder);
uri:要查询的目标
projection:返回的列(String[])
selection:where子句
selectionArgs:如果where子句存在?占位符,则这里需要提供参数
sortOrder:order自居
对于projection,如果不知道具体有哪些列,则会很难进行查询,所以一般应该提供一个对应表的Columns类,例如
People类对象一个PeopleColumns类,该类提供表的一些信息
-public abstract Uri insert(Uri uri, ContentValues values);
关键类android.content.ContentValues,android.content.ContentResolver
Android使用类ContentValues(键值对)来保存即将插入的单一记录的值.
-public abstract int update(Uri uri, ContentValues values, String selection,String[] selectionArgs);
uri:更新的目标
values:ContentValues对象
where:where子句
selectionArgs:传入where子句的参数
返回受影响行数.
-public abstract int delete(Uri uri, String selection, String[] selectionArgs);
与Update类似,返回受影响行数
每个函数我们都可以用SQLiteDatabase下的对应函数来实现,也可以用ContentProvider下的对象函数来实现(待研究)
其中query()函数还可以使用SQLiteQueryBuilder辅助类来实现
SQLiteQueryBuilder能更方便查询的设置,例如projection的映射,select的生成等(详细讲源代码)
ContentProvider配置
ContentProvider是Android四大基础组件之一,需要在AndroidManifest.xml中进行配置,代码如下
&provider android:name=".MyProvider"&&/provider&
文章评论 以下网友留言只代表其个人观点,不代表本网站的观点和立场。Android_Storage(9)
ContentProvider何时创建?
1、ContentProvider所在的Process启动了,ContentProvider就会在ActivityThread中启动。
2、从数据共享的角度出发,ContentProvider应该是Android在系统启动时就创建了,否则就谈不上数据共享了。这就要求在AndroidManifest.XML中使用&provider&元素明确定义。&
SQLiteDatabase方法何时执行?
1、SQLiteOpenHelper会自动检测数据库文件是否存在。如果存在,会打开这个数据库,在这种情况下就不会调用onCreate()方法。如果数据库文件不存在,SQLiteOpenHelper首先会创建一个数据库文件,然后打开这个数据库,最后调用onCreate()方法。因此,onCreate()方法一般用来在新创建的数据库中建立表、视图等数据库组建。也就是说oncreate()方法在数据库文件第一次创建时调用。
2、如果数据库文件不存在,只有oncreate()被调用(该方法在创建数据库时被调用一次)。如果数据库文件存在,会调用onupdate()方法升级数据库,并更新版本号。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:131063次
积分:1880
积分:1880
排名:第17416名
转载:303篇
(61)(83)(85)(21)(47)(10)Android ContentProvider的介绍(很详细) -
- ITeye技术网站
博客分类:
一、ContentProvider的概念  ContentProvider:为存储和获取数据提供统一的接口。可以在不同的应用程序之间共享数据。Android已经为常见的一些数据提供了默认的ContentProvider  1、ContentProvider使用表的形式来组织数据   无论数据的来源是什么,ContentProvider都会认为是一种表,然后把数据组织成表格  2、ContentProvider提供的方法   query:查询   insert:插入   update:更新   delete:删除   getType:得到数据类型   onCreate:创建数据时调用的回调函数  3、每个ContentProvider都有一个公共的URI,这个URI用于表示这个ContentProvider所提供的数据。Android所提供的ContentProvider都存放在android.provider包当中  二、ContentProvider的内部原理  自定义一个ContentProvider,来实现内部原理  步骤:  1、定义一个CONTENT_URI常量(里面的字符串必须是唯一)  Public static final Uri CONTENT_URI = Uri.parse("content://com.WangWeiDa.MyContentprovider");  如果有子表,URI为:  Public static final Uri CONTENT_URI = Uri.parse("content://com.WangWeiDa.MyContentProvider/users");  2、定义一个类,继承ContentProvider  Public class MyContentProvider extends ContentProvider  3、实现ContentProvider的所有方法(query、insert、update、delete、getType、onCreate)  package com.WangWeiDa.    import java.util.HashM    import com.WangWeiDa.cp.MyContentProviderMetaData.UserTableMetaD  import com.WangWeiDa.data.DatabaseH    import android.content.ContentP  import android.content.ContentU  import android.content.ContentV  import android.content.UriM  import android.database.C  import android.database.sqlite.SQLiteD  import android.database.sqlite.SQLiteQueryB  import android.net.U  import android.text.TextU    public class MyContentProvider extends ContentProvider {   //访问表的所有列   public static final int INCOMING_USER_COLLECTION = 1;   //访问单独的列   public static final int INCOMING_USER_SINGLE = 2;   //操作URI的类   public static final UriMatcher uriM   //为UriMatcher添加自定义的URI   static{   uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);   uriMatcher.addURI(MyContentProviderMetaData.AUTHORITIES,"/user",   INCOMING_USER_COLLECTION);   uriMatcher.addURI(MyContentProviderMetaData.AUTHORITIES,"/user/#",   INCOMING_USER_SINGLE);     }   private DatabaseH   //为数据库表字段起别名   public static HashMap userProjectionM   static   {   userProjectionMap = new HashMap();   userProjectionMap.put(UserTableMetaData._ID,UserTableMetaData._ID);   userProjectionMap.put(UserTableMetaData.USER_NAME, UserTableMetaData.USER_NAME);   }   /**   * 删除表数据   */   @Override   public int delete(Uri uri, String selection, String[] selectionArgs) {   System.out.println("delete");   //得到一个可写的数据库   SQLiteDatabase db = dh.getWritableDatabase();   //执行删除,得到删除的行数   int count = db.delete(UserTableMetaData.TABLE_NAME, selection, selectionArgs);     }   /**   * 数据库访问类型   */   @Override   public String getType(Uri uri) {   System.out.println("getType");   //根据用户请求,得到数据类型   switch (uriMatcher.match(uri)) {   case INCOMING_USER_COLLECTION:   return MyContentProviderMetaData.UserTableMetaData.CONTENT_TYPE;   case INCOMING_USER_SINGLE:   return MyContentProviderMetaData.UserTableMetaData.CONTENT_TYPE_ITEM;   default:   throw new IllegalArgumentException("UnKnown URI"+uri);   }   }   /**   * 插入数据   */   @Override   public Uri insert(Uri uri, ContentValues values) {   //得到一个可写的数据库   SQLiteDatabase db = dh.getWritableDatabase();   //向指定的表插入数据,得到返回的Id   long rowId = db.insert(UserTableMetaData.TABLE_NAME, null, values);   if(rowId & 0){//判断插入是否执行成功   //如果添加成功,利用新添加的Id和   Uri insertedUserUri = ContentUris.withAppendedId(UserTableMetaData.CONTENT_URI, rowId);   //通知监听器,数据已经改变   getContext().getContentResolver().notifyChange(insertedUserUri, null);   return insertedUserU   }     }   /**   * 创建ContentProvider时调用的回调函数   */   @Override   public boolean onCreate() {   System.out.println("onCreate");   //得到数据库帮助类   dh = new DatabaseHelp(getContext(),MyContentProviderMetaData.DATABASE_NAME);     }   /**   * 查询数据库   */   @Override   public Cursor query(Uri uri, String[] projection, String selection,   String[] selectionArgs, String sortOrder) {   //创建一个执行查询的Sqlite   SQLiteQueryBuilder qb = new SQLiteQueryBuilder();   //判断用户请求,查询所有还是单个   switch(uriMatcher.match(uri)){   case INCOMING_USER_COLLECTION:   //设置要查询的表名   qb.setTables(UserTableMetaData.TABLE_NAME);   //设置表字段的别名   qb.setProjectionMap(userProjectionMap);     case INCOMING_USER_SINGLE:   qb.setTables(UserTableMetaData.TABLE_NAME);   qb.setProjectionMap(userProjectionMap);   //追加条件,getPathSegments()得到用户请求的Uri地址截取的数组,get(1)得到去掉地址中/以后的第二个元素   qb.appendWhere(UserTableMetaData._ID + "=" + uri.getPathSegments().get(1));     }   //设置排序   String orderBy;   if(TextUtils.isEmpty(sortOrder)){   orderBy = UserTableMetaData.DEFAULT_SORT_ORDER;   }   else{   orderBy = sortO   }   //得到一个可读的数据库   SQLiteDatabase db = dh.getReadableDatabase();   //执行查询,把输入传入   Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy);   //设置监听   c.setNotificationUri(getContext().getContentResolver(), uri);       }   /**   * 更新数据库   */   @Override   public int update(Uri uri, ContentValues values, String selection,   String[] selectionArgs) {   System.out.println("update");   //得到一个可写的数据库   SQLiteDatabase db = dh.getWritableDatabase();   //执行更新语句,得到更新的条数   int count = db.update(UserTableMetaData.TABLE_NAME, values, selection, selectionArgs);     }    }    4、在AndroidMinifest.xml中进行声明    
   android:name=".cp.MyContentProvider"  
   android:authorities="com.WangWeiDa.cp.MyContentProvider"   /&  **为ContentProvider提供一个常量类MyContentProviderMetaData.java  package com.WangWeiDa.    import android.net.U  import android.provider.BaseC    public class MyContentProviderMetaData {   //URI的指定,此处的字符串必须和声明的authorities一致   public static final String AUTHORITIES = "com.wangweida.cp.MyContentProvider";   //数据库名称   public static final String DATABASE_NAME = "myContentProvider.db";   //数据库的版本   public static final int DATABASE_VERSION = 1;   //表名    public static final String USERS_TABLE_NAME = "user";      public static final class UserTableMetaData implements BaseColumns{   //表名   public static final String TABLE_NAME = "user";   //访问该ContentProvider的URI   public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITIES + "/user");   //该ContentProvider所返回的数据类型的定义   public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.myprovider.user";   public static final String CONTENT_TYPE_ITEM = "vnd.android.cursor.item/vnd.myprovider.user";   //列名   public static final String USER_NAME = "name";   //默认的排序方法   public static final String DEFAULT_SORT_ORDER = "_id desc";   }    }
浏览 107912
xiechengfa
浏览: 397421 次
来自: 上海
困惑了很久,终于找到答案了
pixels = dps * (density / 160). ...
楼主给力,解决了我遇到的问题
你好,我转载了您的此篇博客,如果有版权问题,请告诉我,谢谢!转 ...
请教您个问题,如何将drawable对象转换为id类型?}

我要回帖

更多关于 contentprovider 权限 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信