Android数据存储方式之:ContentProvider

ContentProvider是Android的四大组件之一,可见其重要性。我们使用到ContentProvider时,也要同Activity等其它组件一样,在AndroidManifest.xml中注册对应的组件才能使用。为什么会用ContentProvider来作为数据存储方式之一呢?

ContentProvider在android中的作用是对外共享数据(应用之间数据共享),可以通过ContentProvider把应用中的数据共享给其他应用访问,其他应用可以通过ContentProvider对你应用中的数据进行添删改查。与其它数据共享方式相比:如果采用文件操作模式对外共享数据,数据的访问方式会因数据存储的方式而不同,导致数据的访问方式无法统一,如:采用xml文件对外共享数据,需要进行xml解析才能读取数据;采用sharedpreferences共享数据,需要使用sharedpreferences
API读取数据。使用ContentProvider对外共享数据的好处是统一了数据的访问方式。

Android中的ContentProvider机制可支持在多个应用中存储和读取数据。这也是跨应用共享数据的方式之一,还有文件,sharePreference,SQLite数据库等方式存储共享数据库,但是ContentProvider更好的提供了数据共享接口的统一性。在android系统中,没有一个公共的内存区域,供多个应用共享存储数据。Android提供了一些主要数据类型的Content
provider,比如音频、视频、图片和私人通讯录等。可在android.provider包下面找到一些android提供的Content provider。可以获得这些Content provider,查询它们包含的数据,当然前提是已获得适当的读取权限。Android系统将这种机制应用到方方面面。比如:联系人提供器专为不同应用程序提供联系人数据;设置提供器专为不同应用程序提供系统配置信息,包括内置的设置应用程序等。

今天用单元测试的方式简单介绍ContentProvider的使用:

-------------------------------使用ContentProvider共享数据,一般用到Sqlite数据库-----------------------------------------------------------

public class DBHelpTool {

private static DatabaseHelper dbHelper;

private static SQLiteDatabase db;

/**数据库名*/

private static final String DB_NAME = "kawa.db";

/**数据库版本*/

private static final int DB_VERSION = 1;

private final Context mContent;

public DBHelpTool(Context mContent) {

this.mContent = mContent;

}

/**定义一个抽象类,用于数据库的创建和版本的管理 */

private static class DatabaseHelper extends SQLiteOpenHelper {

DatabaseHelper(Context context) {

super(context, DB_NAME, null, DB_VERSION);

}

@Override

public void onCreate(SQLiteDatabase db) {

/**创建一个老师teacher表,三个字段分别是_id(自增长主键),name和age*/

String sql = "create table if not exists  teacher (_id integer primary key autoincrement, name text,age integer)";

db.execSQL(sql);

}

@Override

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

// 数据库升级操作

}

}

/**打开数据库操作*/

public DBHelpTool open() throws SQLException {

dbHelper = new DatabaseHelper(mContent);

db = dbHelper.getWritableDatabase();

return this;

}

/**关闭数据库操作*/

public void closeclose() {

db.close();

dbHelper.close();

}

/**

* 插入数据

* 参数:tableName 表名

* values 要插入的列对应值

*/

public long insert(String tableName, ContentValues values) {

return db.insert(tableName, null, values);

}

/**

* 删除数据

* 参数:tableName 表名

* deleteCondition 删除的条件

* deleteArgs 如果deleteCondition中有“=?”号,将用此数组中的值替换

*/

public int delete(String tableName, String deleteCondition, String[] deleteArgs) {

return db.delete(tableName, deleteCondition, deleteArgs);

}

/**

* 修改数据

* 参数:tableName 表名

* initialValues 要更新的列

* selection 更新的条件

* selectArgs 如果selection中有“=?”号,将用此数组中的值替换

*/

public int update(String tableName, ContentValues initialValues, String selection, String[] selectArgs) {

int returnValue = db.update(tableName, initialValues, selection, selectArgs);

return returnValue;

}

/**

* 查询相应条件的所有数据

* 参数:tableName 表名

* columns 返回的列

* selection 查询条件

* selectArgs 如果selection中有“?”号,将用此数组中的值替换

*/

public Cursor findList(String tableName, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy) {

return db.query(tableName, columns, selection, selectionArgs, groupBy, having, orderBy);

}

----------------------------------对应的数据表teacher实体类------------------------------------------------

public class Teacher implements Serializable {

private static final long serialVersionUID = 1L;

private int id;

private String name;

private int age;

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

@Override

public int hashCode() {

final int prime = 31;

int result = 1;

result = prime * result + age;

result = prime * result + id;

result = prime * result + ((name == null) ? 0 : name.hashCode());

return result;

}

@Override

public boolean equals(Object obj) {

if (this == obj)

return true;

if (obj == null)

return false;

if (getClass() != obj.getClass())

return false;

Teacher other = (Teacher) obj;

if (age != other.age)

return false;

if (id != other.id)

return false;

if (name == null) {

if (other.name != null)

return false;

} else if (!name.equals(other.name))

return false;

return true;

}

@Override

public String toString() {

return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";

}

}

------------------------简单的常量类-------------------------------------------------

public class UrlConstant {

public static String PROVIDER_URL = "com.ldm.provider.myprovider";

public static String TABLE_NAME = "teacher";

}

--------------------------今天的主角,我们的ContentProvider,继承ContentProvider就对应有增删改查方法--------------------------------------

public class TestProvider extends ContentProvider {

private DBHelpTool mDBTool;

/**匹配工具类UriMatcher:

* Android中是用Uri代表要操作的数据,所以我们需要解析Uri并从Uri中获取数据。

* Android系统提供了两个操作Uri的工具类:分别为UriMatcher和ContentUris

* UriMatcher类用于匹配Uri,它的用法如下:

* 首先第一步把你需要匹配Uri路径全部给注册,如下:

* 常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码UriMatcher  sMatcher = new UriMatcher(UriMatcher.NO_MATCH);

* 给注册的Uri路径中增加定义好的Uri路径:

* MATCHER.addURI(UrlConstant.CONTENTPROVIDER, "stu", UrlConstant.TEACHER_LIST);//返回匹配码为1

* MATCHER.addURI(UrlConstant.CONTENTPROVIDER, "stu/#", UrlConstant.TEACHER_DETAIL);//返回匹配码为2

* 注册完需要匹配的Uri后,就可以使用sMatcher.match(uri)方法对输入的Uri进行匹配

**/

private static final UriMatcher MATCHER = new UriMatcher(UriMatcher.NO_MATCH);

private static final int TEACHERS = 1;

private static final int TEACHER = 2;

static {

MATCHER.addURI(UrlConstant.PROVIDER_URL, "person", TEACHERS);

MATCHER.addURI(UrlConstant.PROVIDER_URL, "person/#", TEACHER);

}

@Override

public boolean onCreate() {

mDBTool = new DBHelpTool(this.getContext());

mDBTool.open();

return false;

}

/**查询数据*/

@Override

public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {

switch (MATCHER.match(uri)) {

case TEACHERS:

return mDBTool.findList("person", projection, selection, selectionArgs, null, null, sortOrder);

case TEACHER:

/** 查询某个ID的数据: 通过ContentUris这个工具类解释出ID

* ContentUris 类用于获取Uri路径后面的ID部分

* 1)为路径加上ID: withAppendedId(uri, id)

* 2)从路径中获取ID: parseId(uri)

* */

long id = ContentUris.parseId(uri);

String where = " _id=" + id;

if (!"".equals(selection) && selection != null) {

where = selection + " and " + where;

}

return mDBTool.findList(UrlConstant.TABLE_NAME, projection, where, selectionArgs, null, null, sortOrder);

default:

throw new IllegalArgumentException("unknow uri" + uri.toString());

}

}

/**返回当前操作的数据的mimeType*/

@Override

public String getType(Uri uri) {

switch (MATCHER.match(uri)) {

case TEACHERS:

return "vnd.android.cursor.dir/teacher";

case TEACHER:

return "vnd.android.cursor.item/teacher";

default:

throw new IllegalArgumentException("Error Uri:" + uri.toString());

}

}

/**添加数据*/

@Override

public Uri insert(Uri uri, ContentValues values) {

Uri insertUri = null;

switch (MATCHER.match(uri)) {

case TEACHERS:

long rowid = mDBTool.insert(UrlConstant.TABLE_NAME, values);

insertUri = ContentUris.withAppendedId(uri, rowid);

break;

default:

throw new IllegalArgumentException("Error Uri:" + uri.toString());

}

return insertUri;

}

/**删除数据*/

@Override

public int delete(Uri uri, String selection, String[] selectionArgs) {

int count = 0;

switch (MATCHER.match(uri)) {

case TEACHERS:

count = mDBTool.delete(UrlConstant.TABLE_NAME, selection, selectionArgs);

return count;

case TEACHER:

long id = ContentUris.parseId(uri);

String where = "_id=" + id;

if (selection != null && !"".equals(selection)) {

where = selection + " and " + where;

}

count = mDBTool.delete("person", where, selectionArgs);

return count;

default:

throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());

}

}

/**修改数据*/

@Override

public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {

int count = 0;

switch (MATCHER.match(uri)) {

case TEACHERS:

count = mDBTool.update(UrlConstant.TABLE_NAME, values, selection, selectionArgs);

break;

case TEACHER:

// 通过ContentUri工具类得到ID

long id = ContentUris.parseId(uri);

String where = "_id=" + id;

if (selection != null && !"".equals(selection)) {

where = selection + " and " + where;

}

count = mDBTool.update("person", values, where, selectionArgs);

break;

default:

throw new IllegalArgumentException("Error Uri:" + uri.toString());

}

return count;

}

}

------------------------单元测试,相当于另外一个应用,对我们提供的ContentProvider进行数据操作-------------------------------

/**

* 先介绍下Uri:

*  Uri代表了要操作的数据,Uri主要包含了两部分信息:

*  1.需要操作的ContentProvider ,2.对ContentProvider中的什么数据进行操作。

*  一个Uri由以下几部分组成:

*   1.scheme:ContentProvider的scheme已经由Android所规定(不能更改):content://。

*   2.主机名(或Authority):用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。

*   3.路径(path):可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下:

*   ? 要操作teacher表中id为10的记录,可以构建这样的路径:/teacher/10

*   ? 要操作teacher表中id为10的记录的name字段, teacher/10/name

*   ? 要操作teacher表中的所有记录,可以构建这样的路径:/teacher

*   要操作的数据不一定来自数据库,也可以是文件等他存储方式,如下:

*   要操作xml文件中teacher节点下的name节点,可以构建这样的路径:/teacher/name

*   如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下:

*   Uri uri = Uri.parse("content://com.ldm.provider.testprovider/teacher")

*/

public class ProjectTestCase extends AndroidTestCase {

/**添加数据操作*/

public void testInsert() throws Exception {

ContentResolver contentResolver = this.getContext().getContentResolver();

Uri url = Uri.parse("content://" + UrlConstant.PROVIDER_URL + "/person");

ContentValues values = new ContentValues();

values.put("name", "liming");

values.put("age", 22);

contentResolver.insert(url, values);

}

/**删除数据操作*/

public void testDelete() throws Exception {

ContentResolver contentResolver = this.getContext().getContentResolver();

Uri url = Uri.parse("content://" + UrlConstant.PROVIDER_URL + "/person/1");

contentResolver.delete(url, null, null);

}

/**更新数据操作*/

public void testUpdate() throws Exception {

ContentResolver contentResolver = this.getContext().getContentResolver();

Uri url = Uri.parse("content://" + UrlConstant.PROVIDER_URL + "/person/1");

ContentValues values = new ContentValues();

values.put("name", "wangwu");

values.put("age", 20);

contentResolver.update(url, values, null, null);

}

/**查询数据操作*/

public void testQuery() throws Exception {

ContentResolver contentResolver = this.getContext().getContentResolver();

Uri url = Uri.parse("content://" + UrlConstant.PROVIDER_URL + "/person");

Cursor cursor = contentResolver.query(url, new String[] { "_id", "name", "age" }, null, null, "_id");

while (cursor.moveToNext()) {

System.out.println("_id:" + cursor.getInt(cursor.getColumnIndex("_id")));

System.out.println("name:" + cursor.getString(cursor.getColumnIndex("name")));

System.out.println("age:" + cursor.getInt(cursor.getColumnIndex("age")));

}

}

}

---------------------------还是要说说AndroidManifest.xml中对应的组件注册---------------------------------------------------------------

ContentProvier注册:

<provider

android:name="com.ldm.test.provider.TestProvider"

android:authorities="com.ldm.provider.myprovider" >和UrlConstant中的PROVIDER_URL一致

</provider>

注册单元测试:

<uses-library android:name="android.test.runner" />

<instrumentation

android:name="android.test.InstrumentationTestRunner"

android:label="Tests for My App"

android:targetPackage="com.ldm.test" />应用包名

时间: 2024-08-29 12:28:46

Android数据存储方式之:ContentProvider的相关文章

Android数据存储方式

在Android开发中,我们有时需要存储一些数据 便于我们清楚知道存储的信息,很直观的看到 可以用来分析.Java中 中也有一些存储方式,在这里我就不一一介绍了,感兴趣的盆友http://blog.csdn.net/aaa1117a8w5s6d/article/details/8251456,今天的重点是来研究Android中的数据存储,Android中提供了几种方式来存储,下面来一一为大家介绍. 在Android系统中 提供了四种存储方式 分别是SQLite .File.SharedPrefe

Android 数据存储方式分为哪几种?

10道题值得思考 第一道题 1.Android 数据存储方式分为哪几种? SharedPreferences存储数据 2. CotentProvider内容提供者 3. 文件存储 4. 数据库存储(Sqlite) 5.网络存储 2. NDK是什么? 1. 一系列工具类的集合 2. Arm指令集 3. NDK提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成apk.这些工具对开发者的帮助是巨大的. NDK集成了交叉编译器,并提供了相应的mk文件隔离

安卓中的数据存储方式以及ContentProvider的简单介绍

1.介绍android的数据存储方式 File存储 sharedPrefrence存储方式 conmtentprovider sqlitedatabase 网络存储 2.请介绍下ContentProvider是如何实现数据共享的 安卓中如果想将自己应用程序的数据暴露给其他的应用程序的时候就需要创建内容提供者.第三方可以通过contentResolver来访问该provider 3.为什么要使用ContentProvider?它和sql的实现上有什么差别? ContentProvider屏蔽了数据

Android数据存储方式简括

Android提供以下四种存储方式: SharePreference SQLite File ContentProvider 如果要实现数据共享,正确的方式是使用ContentProvider SharedPreference "用户的偏好设置"通常用来存储程序的一些配置信息. 其存储在"data/data/程序包名/shared_prefs目录下. 使用键-值的形式来存储数据;我们只需要调用SharedPreferences的getXxx(name), 就可以根据键获得对应

Android数据存储方式之SharedPreferences

Android平台给我们提供了一个SharedPreferences类,它是一个轻量级的存储类,特别适合用于保存软件配置参数.使用SharedPreferences保存数据,其背后是用xml文件存放数据,文件存放在/data/data/<package name>/shared_prefs目录下: 存储: SharedPreferences sp=getSharedPreferences("UItest",Activity.MODE_APPEND);SharedPrefer

android 数据存储方式

韩梦飞沙  韩亚飞  [email protected]  yue31313  han_meng_fei_sha 1,文件 2,内容提供者 3,偏好设置 4,数据库 5,网络存储. 网络存储,就是上传到网络,从网络获取 或者下载 数据.

android的数据存储方式

数据存储在开发中是使用最频繁的,Android平台中实现数据存储主要有5种方式,分别是: 1 SQLite: SQLite是一个轻量级嵌入式数据库,支持基本SQL语法,是常被采用的一种数据存储方式.Android为此数据库提供了一个名为SQLiteDatabase的类,封装了一些操作数据库的API. 2 SharedPreference:SharedPreferences也是一种轻型的数据存储方式,它的本质是基于XML文件存储key-value键值对数据,通常用来存储一些简单的配置信息.其存储位

Android数据存储之SharedPreferences浅析

SharedPreferences 是 Android 数据存储方式中的一种,特别适合用来存储少量的.格式简单的数据,比如应用程序的各种配置信息,如是否打开音效,是否开启震动等等. SharedPreferences 存储数据的位置和格式 SharedPreferences 将数据以键值对的形式,存储在 /data/data/<package name>/shared_prefs 目录下面,以 XML 的格式保存,该 XML 文件的根元素是 <map.../>,该元素里每个子元素代

android五种数据存储方式

在Android中提供了如下五种数据存储方式: SharedPreferences 文件存储 SQLite数据库方式 内容提供器(ContentProvider) 网络存储 下面具体介绍一下这五种数据存储方式的用法. 1. SharedPreferences SharedPreferences是android平台上的一个轻量级存储类,主要保存一些常用的配置信息.可以保存long.int.String类型数据. SharedPreferences以键值对方式读取和存入,最终会以XML方式保存数据,