实例讲解Android中ContentProvider组件的使用方法
contentprovider基本使用
为了在应用程序之间交换数据,android提供了contentprovider,contentprovider是不同应用程序之间进行数据交换的标准api,当一个应用程序需要把自己的数据暴露给其他程序使用时,该应用程序就可以通过提供contentprovider来实现,其他应用程序就可以通过contentresolver来操作contentprovider暴露的数据。
实现contentprovider的步骤:
1)编写一个类,继承contentprovider,并且重写里面的crud方法。
2)在androidmanifest.xml文件中注册provider。
在androidmanifest.xml中注册provider需要以下3个属性:
android:name provider的实现类。
android:authorities provider的uri。
android:exported provider是否暴露给其他程序。
contentresovler操作contentprovider:
1)获取contentresolver,getcontentresovler()方法来自于contextwrapper,所以activity和service中都可以使用。
2)调用curd方法,通过参数url,调用指定的contentprovider的方法。
下面是一个demo,向contentprovider中插入一条数据,并且返回到listview中。
main.xml:
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".main" > <listview android:id="@+id/listview" android:layout_width="match_parent" android:layout_height="wrap_content" /> </relativelayout>
mysqliteopenhelper类
package com.app.dao; import android.content.context; import android.database.sqlite.sqlitedatabase; import android.database.sqlite.sqlitedatabase.cursorfactory; import android.database.sqlite.sqliteopenhelper; public class mysqliteopenhelper extends sqliteopenhelper { public mysqliteopenhelper(context context, string name, cursorfactory factory, int version) { super(context, name, factory, version); } @override public void oncreate(sqlitedatabase db) { string create_sql = "create table tb_test(_id integer primary key autoincrement,name,gender,age)"; db.execsql(create_sql); } @override public void onupgrade(sqlitedatabase db, int oldversion, int newversion) { } }
mycontentprovider类
package com.app.dao; import android.content.contentprovider; import android.content.contentvalues; import android.database.cursor; import android.net.uri; public class mycontentprovider extends contentprovider{ mysqliteopenhelper helper=null; @override public int delete(uri arg0, string arg1, string[] arg2) { return 0; } @override public string gettype(uri arg0) { // todo auto-generated method stub return null; } @override public uri insert(uri arg0, contentvalues values) { string insert_sql="insert into tb_test values(null,'wx','boy',17)"; helper.getreadabledatabase().execsql(insert_sql); return null; } @override public boolean oncreate() { helper=new mysqliteopenhelper(this.getcontext(),"test.db3",null,1); return true; } @override public cursor query(uri arg0, string[] arg1, string arg2, string[] arg3, string arg4) { string query_sql="select * from tb_test"; cursor cursor=helper.getreadabledatabase().rawquery(query_sql, null); return cursor; } @override public int update(uri arg0, contentvalues arg1, string arg2, string[] arg3) { // todo auto-generated method stub return 0; } }
listview的显示界面show.xml
<?xml version="1.0" encoding="utf-8"?> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <textview android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <textview android:id="@+id/gender" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginleft="60dp" /> <textview android:id="@+id/age" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginleft="60dp" /> </linearlayout>
main.java
package com.app.main; import android.annotation.suppresslint; import android.app.activity; import android.content.contentresolver; import android.database.cursor; import android.net.uri; import android.os.bundle; import android.support.v4.widget.cursoradapter; import android.widget.listview; import android.widget.simplecursoradapter; public class main extends activity { contentresolver resolver = null; listview lv = null; @suppresslint("newapi") @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.main); lv = (listview) this.findviewbyid(r.id.listview); resolver = this.getcontentresolver(); string str = "content://com.app.test.db/"; uri uri = uri.parse(str); resolver.insert(uri, null); cursor cursor = resolver.query(uri, null, null, null, null); simplecursoradapter adapter = new simplecursoradapter(this, r.layout.show, cursor, new string[] { "name", "gender", "age" }, new int[] { r.id.name, r.id.gender, r.id.age }, cursoradapter.flag_register_content_observer); lv.setadapter(adapter); } }
实现效果:(执行了3次插入后的效果)
contentprovider的单元测试
contentprovider是android的四大组件之一,在编写代码的时候最好是加上单元测试,这样可以确定对数据的crud的正确。本篇文章主要介绍contentprovider中两个主要辅助类的使用还有单元测试的在contentprovider中的使用。
需要用到的两个辅助类:urimatcher类和contenturis类。
urimatcher类:能够对输入的uri参数就行匹配,以确定对什么表执行什么样的操作。
contenturis类:有些方法需要返回uri,运用此类可以方便的生成uri类。
对于单元测试,个人觉得非常有必要在今后写代码的时候使用,这样可以非常准确的确定代码的正确性。
使用单元测试的步骤:
1)加入instrumentation,这个部分的代码是固定,也可以完全在adt提供的向导中导入。
<instrumentation android:name="android.test.instrumentationtestrunner" android:targetpackage="com.example.android_contentprovider" > </instrumentation>
2)添加<uses-library>,这个部分的代码也是固定的写法。
<uses-library android:name="android.test.runner" />
好了,必备的知识已经讲完了,现在上代码:
1)生成一个sqlitedatabase类,这个是必需的类mysqliteopenhelper类
package com.app.db; import android.content.context; import android.database.sqlite.sqlitedatabase; import android.database.sqlite.sqlitedatabase.cursorfactory; import android.database.sqlite.sqliteopenhelper; public class mysqliteopenhelper extends sqliteopenhelper { private static string db_name = "test.db3"; private static int version = 1; public mysqliteopenhelper(context context) { super(context, db_name, null, version); } @override public void oncreate(sqlitedatabase db) { //建表语句 string create_student = "create table student(_id integer primary key autoincrement,name varchar(10),age integer,gender vachar(10))"; db.execsql(create_student); //千万不能执行这句 // db.close(); } @override public void onupgrade(sqlitedatabase arg0, int arg1, int arg2) { } }
然后添加我们需要的mycontentprovider类:
package com.app.contentprovider; import com.app.db.mysqliteopenhelper; import android.content.contentprovider; import android.content.contenturis; import android.content.contentvalues; import android.content.urimatcher; import android.database.cursor; import android.database.sqlite.sqlitedatabase; import android.net.uri; import android.util.log; public class mycontentprovider extends contentprovider { mysqliteopenhelper helper = null; private static urimatcher matcher = new urimatcher(urimatcher.no_match); // 匹配单条记录 private static final int student = 1; // 匹配多条记录 private static final int students = 2; static { matcher.adduri("com.app.wx", "student/#", student); matcher.adduri("com.app.wx", "student", students); } @override public int delete(uri uri, string selection, string[] selectionargs) { sqlitedatabase db = helper.getwritabledatabase(); int action = matcher.match(uri); switch (action) { // 匹配单条记录 case student: long id = contenturis.parseid(uri); //获取单条记录的id号 string delete_id = "_id=" + id; if (selection != null) { delete_id += delete_id + " and " + selection; } db.delete("student", delete_id, selectionargs); break; // 匹配多条记录 case students: db.delete("student", selection, selectionargs); break; } return 0; } //必需实现这个方法,这个方法与intent有关系,以后再讲 @override public string gettype(uri uri) { int code = matcher.match(uri); switch (code) { case student: return "vnd.android.cursor.item/student_item"; case students: return "vnd.android.cursor.dir/students"; default: return null; } } @override public uri insert(uri uri, contentvalues values) { sqlitedatabase db = helper.getwritabledatabase(); int action = matcher.match(uri); switch (action) { case students: long id1 = db.insert("student", "_id", values); log.i("--------", contenturis.withappendedid(uri, id1).tostring()); return contenturis.withappendedid(uri, id1); } return null; } @override public boolean oncreate() { helper = new mysqliteopenhelper(this.getcontext()); return true; } @override public cursor query(uri uri, string[] projection, string selection, string[] selectionargs, string orderby) { sqlitedatabase db = helper.getwritabledatabase(); cursor cursor = null; int action = matcher.match(uri); switch (action) { case students: cursor = db.query("student", projection, selection, selectionargs, null, null, orderby); break; } system.out.println("-----------count:" + cursor.getcount()); return cursor; } @override public int update(uri uri, contentvalues values, string selection, string[] arg3) { int count = -1; sqlitedatabase db = helper.getwritabledatabase(); int action = matcher.match(uri); switch (action) { case student: // 以id来处理更新 long id = contenturis.parseid(uri); string id_selection = "_id=" + id; if (selection != null && !selection.equals("")) { id_selection = id_selection + " and " + values; } count = db.update("student", values, id_selection, arg3); system.out.println("----------count:" + count); break; } return count; } }
这个类很长,但是执行的方法都是比较常见的curd的方法,重要的是urimatcher和contenturis类的使用。
接着执行单元测试类:test
package com.app.contentprovider; import android.content.contentresolver; import android.content.contentvalues; import android.database.cursor; import android.net.uri; import android.test.androidtestcase; import android.util.log; public class test extends androidtestcase { public void insert() { contentresolver resolver = this.getcontext().getcontentresolver(); string str = "content://com.app.wx/student"; contentvalues values = new contentvalues(); values.put("name", "wzq"); values.put("age", 18); values.put("gender", "boy"); resolver.insert(uri.parse(str), values); } public void update() { contentresolver resolver = this.getcontext().getcontentresolver(); string str = "content://com.app.wx/student/2"; contentvalues values = new contentvalues(); values.put("name", "哈哈"); resolver.update(uri.parse(str), values, null, null); } public void query() { contentresolver resolver = this.getcontext().getcontentresolver(); string str = "content://com.app.wx/student"; uri uri = uri.parse(str); cursor cursor = resolver.query(uri, new string[] { "_id", "name,age,gender" }, null, null, "_id desc"); log.d("------count",cursor.getcount()+""); } public void delete() { contentresolver resolver = this.getcontext().getcontentresolver(); string str = "content://com.app.wx/student/2"; uri uri = uri.parse(str); long id=resolver.delete(uri, null, null); } }
执行insert方法之后(执行了三次):
执行了update方法之后:
执行了query方法之后:
执行了delete方法之后:
推荐阅读
-
实例讲解Android中ContentProvider组件的使用方法
-
实例讲解Android中的AutoCompleteTextView自动补全组件
-
实例讲解Android应用中自定义组合控件的方法
-
实例讲解Android中的AIDL内部进程通信接口使用
-
通过实例简单讲解Android App中的Activity组件
-
实例解析Android系统中的ContentProvider组件用法
-
实例讲解Android中ContentProvider组件的使用方法
-
讲解Android中的Widget及AppWidget小工具的创建实例
-
实例讲解Android中ViewPager组件的一些进阶使用技巧
-
实例讲解Android应用开发中TabHost的使用要点