博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android(四)数据存储之四ContentProvider
阅读量:4069 次
发布时间:2019-05-25

本文共 10992 字,大约阅读时间需要 36 分钟。

<p>早上我们简要的对SQLite进行回顾,然后将SQLite的事务管理和SQLiteDataBase提供的Insert、Update、Delete、Query方法进行了简单的讲解。 </p> <p>今日的重点内容是ContentProvider(内容提供者)和网络存储,我将对这两大内容进行总结。关于SQLiteDataBase提供的便捷方法,它们会在ContentProvider被使用。SQLite的事务管理比较简单,昨天有简要介绍,今日就不做总结了。</p> <p>ContentProvider和网络存储将分为两篇日志,本篇总结ContentProvider。</p> <p><strong>一、ContentProvider简介</strong></p> <p>当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据。虽然使用其他方法也可以对外共享数据,但数据访问方式会因数据存储的方式而不同,如:采用文件方式对外共享数据,需要进行文件操作读写数据;采用sharedpreferences共享数据,需要使用sharedpreferences API读写数据。而使用ContentProvider共享数据的好处是统一了数据访问方式。</p> <p><strong>二、Uri类简介</strong></p> <p>Uri代表了要操作的数据,Uri主要包含了两部分信息:1.需要操作的ContentProvider ,2.对ContentProvider中的什么数据进行操作,一个Uri由以下几部分组成:</p> <p><img title="2010-03-02 传智播客—Android(四)数据存储之ContentProvider - 长城 - 长城" border="0" alt="2010-03-02 传智播客—Android(四)数据存储之ContentProvider - 长城 - 长城" src="http://lh6.ggpht.com/_FMPy3IVGHrs/S40clPZ8KVI/AAAAAAAABmk/k91r66Ob6Z8/A999AFB360609C72156A0B6AE40DD692850A9A9E.jpg?imgmax=800" width="364" height="65"><br>1.scheme:ContentProvider(内容提供者)的scheme已经由Android所规定为:content://。</p> <p>2.主机名(或Authority):用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。</p> <p>3.路径(path):可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下:</p> <p>· 要操作contact表中id为10的记录,可以构建这样的路径:/contact/10</p> <p>· 要操作contact表中id为10的记录的name字段, contact/10/name</p> <p>· 要操作contact表中的所有记录,可以构建这样的路径:/contact</p> <p>要操作的数据不一定来自数据库,也可以是文件等他存储方式,如下:</p> <p>要操作xml文件中contact节点下的name节点,可以构建这样的路径:/contact/name</p> <p>如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下:</p> <p>Uri uri = Uri.parse("content://com.changcheng.provider.contactprovider/contact")</p> <p><strong>三、UriMatcher、ContentUrist和ContentResolver简介</strong></p> <p>因为Uri代表了要操作的数据,所以我们很经常需要解析Uri,并从Uri中获取数据。Android系统提供了两个用于操作Uri的工具类,分别为UriMatcher 和ContentUris 。掌握它们的使用,会便于我们的开发工作。</p> <p><strong>UriMatcher</strong><strong>:</strong>用于匹配Uri,它的用法如下:</p> <p>1.首先把你需要匹配Uri路径全部给注册上,如下:</p> <p>//常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码(-1)。</p> <p>UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);</p> <p>//如果match()方法匹配content://com.changcheng.sqlite.provider.contactprovider/contact路径,返回匹配码为1</p> <p>uriMatcher.addURI(“com.changcheng.sqlite.provider.contactprovider”, “contact”, 1);//添加需要匹配uri,如果匹配就会返回匹配码</p> <p>//如果match()方法匹配 content://com.changcheng.sqlite.provider.contactprovider/contact/230路径,返回匹配码为2</p> <p>uriMatcher.addURI(“com.changcheng.sqlite.provider.contactprovider”, “contact/#”, 2);//#号为通配符</p> <p>2.注册完需要匹配的Uri后,就可以使用uriMatcher.match(uri)方法对输入的Uri进行匹配,如果匹配就返回匹配码,匹配码是调用addURI()方法传入的第三个参数,假设匹配content://com.changcheng.sqlite.provider.contactprovider/contact路径,返回的匹配码为1。</p> <p><strong>ContentUris</strong><strong>:</strong>用于获取Uri路径后面的ID部分,它有两个比较实用的方法:</p> <p>· withAppendedId(uri, id)用于为路径加上ID部分</p> <p>· parseId(uri)方法用于从路径中获取ID部分</p> <p><strong>ContentResolver</strong><strong>:</strong>当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver 类来完成,要获取ContentResolver 对象,可以使用Activity提供的getContentResolver()方法。 ContentResolver使用insert、delete、update、query方法,来操作数据。</p> <p><strong>四、ContentProvider示例程序</strong></p> <p>我们为昨天的SQLite示例程序添加一个ContentProvider,供其他应用来访问我们的数据。</p> <p><strong>1.</strong><strong>为SQLite示例程序添加ContentProvider类</strong></p> <p><strong>package</strong> com.changcheng.sqlite.provider;</p> <p><strong>import</strong> com.changcheng.sqlite.MyOpenHelper;</p> <p><strong>import</strong> android.content.ContentProvider;</p> <p><strong>import</strong> android.content.ContentUris;</p> <p><strong>import</strong> android.content.ContentValues;</p> <p><strong>import</strong> android.content.UriMatcher;</p> <p><strong>import</strong> android.database.Cursor;</p> <p><strong>import</strong> android.database.sqlite.SQLiteDatabase;</p> <p><strong>import</strong> android.net.Uri;</p> <p><strong>public</strong> <strong>class</strong> ContactContentProvider <strong>extends</strong> ContentProvider {</p> <p>// 通过UriMatcher匹配外部请求</p> <p><strong>private</strong> <strong>static</strong> UriMatcher <em>uriMatcher</em> = <strong>new</strong> UriMatcher(UriMatcher.<em>NO_MATCH</em>);</p> <p>// 通过openHelper进行数据库读写</p> <p><strong>private</strong> MyOpenHelper openHelper;</p> <p>// 匹配状态常量</p> <p><strong>private</strong> <strong>static</strong> <strong>final</strong> <strong>int</strong> <em>CONTACT_LIST</em> = 1;</p> <p><strong>private</strong> <strong>static</strong> <strong>final</strong> <strong>int</strong> <em>CONTACT</em> = 2;</p> <p>// 表名</p> <p><strong>private</strong> <strong>static</strong> <strong>final</strong> String <em>tableName</em> = "contacts";</p> <p>// 添加<u>Uri</u></p> <p><strong>static</strong> {</p> <p><em>uriMatcher</em>.addURI("com.changcheng.sqlite.provider", "contact",</p> <p><em>CONTACT_LIST</em>);</p> <p><em>uriMatcher</em>.addURI("com.changcheng.sqlite.provider", "contact/#",</p> <p><em>CONTACT</em>);</p> <p>}</p> <p>@Override</p> <p><strong>public</strong> <strong>int</strong> delete(Uri uri, String selection, String[] selectionArgs) {</p> <p>SQLiteDatabase db = <strong>this</strong>.openHelper.getWritableDatabase();</p> <p><strong>int</strong> result;</p> <p><strong>switch</strong> (<em>uriMatcher</em>.match(uri)) {</p> <p><strong>case</strong> <em>CONTACT_LIST</em>:</p> <p>result = db.delete(<em>tableName</em>, selection, selectionArgs);</p> <p><strong>break</strong>;</p> <p><strong>case</strong> <em>CONTACT</em>:</p> <p><strong>long</strong> id = ContentUris.<em>parseId</em>(uri);</p> <p>String where = "_id=" + id;</p> <p><strong>if</strong> (selection != <strong>null</strong> && !"".equals(selection)) {</p> <p>where = where + " and " + selection;</p> <p>}</p> <p>result = db.delete(<em>tableName</em>, where, selectionArgs);</p> <p><strong>break</strong>;</p> <p><strong>default</strong>:</p> <p><strong>throw</strong> <strong>new</strong> IllegalArgumentException("Uri IllegalArgument:" + uri);</p> <p>}</p> <p><strong>return</strong> result;</p> <p>}</p> <p>@Override</p> <p><strong>public</strong> String getType(Uri uri) {</p> <p><strong>switch</strong> (<em>uriMatcher</em>.match(uri)) {</p> <p><strong>case</strong> <em>CONTACT_LIST</em>:// 集合类型必须在前面加上vnd.android.cursor.dir/</p> <p><strong>return</strong> "vnd.android.cursor.dir/contactlist";</p> <p><strong>case</strong> <em>CONTACT</em>:// 非集合类型必须在前面加上vnd.android.cursor.item/</p> <p><strong>return</strong> "vnd.android.cursor.item/contact";</p> <p><strong>default</strong>:</p> <p><strong>throw</strong> <strong>new</strong> IllegalArgumentException("Uri IllegalArgument:" + uri);</p> <p>}</p> <p>}</p> <p>@Override</p> <p><strong>public</strong> Uri insert(Uri uri, ContentValues values) {</p> <p>SQLiteDatabase db = <strong>this</strong>.openHelper.getWritableDatabase();</p> <p><strong>long</strong> id;</p> <p><strong>switch</strong> (<em>uriMatcher</em>.match(uri)) {</p> <p><strong>case</strong> <em>CONTACT_LIST</em>:</p> <p>// 因为后台需要生成SQL语句,当values为null时,必须提第二个参数。生成的SQL语句才不会出错!</p> <p>id = db.insert(<em>tableName</em>, "_id", values);</p> <p><strong>return</strong> ContentUris.<em>withAppendedId</em>(uri, id);</p> <p><strong>case</strong> <em>CONTACT</em>:</p> <p>id = db.insert(<em>tableName</em>, "_id", values);</p> <p>String uriPath = uri.toString();</p> <p>String path = uriPath.substring(0, uriPath.lastIndexOf("/")) + id;</p> <p><strong>return</strong> Uri.<em>parse</em>(path);</p> <p><strong>default</strong>:</p> <p><strong>throw</strong> <strong>new</strong> IllegalArgumentException("Uri IllegalArgument:" + uri);</p> <p>}</p> <p>}</p> <p>@Override</p> <p><strong>public</strong> <strong>boolean</strong> onCreate() {</p> <p><strong>this</strong>.openHelper = <strong>new</strong> MyOpenHelper(<strong>this</strong>.getContext());</p> <p><strong>return</strong> <strong>true</strong>;</p> <p>}</p> <p>@Override</p> <p><strong>public</strong> Cursor query(Uri uri, String[] projection, String selection,</p> <p>String[] selectionArgs, String sortOrder) {</p> <p>SQLiteDatabase db = <strong>this</strong>.openHelper.getWritableDatabase();</p> <p><strong>switch</strong> (<em>uriMatcher</em>.match(uri)) {</p> <p><strong>case</strong> <em>CONTACT_LIST</em>:</p> <p><strong>return</strong> db.query(<em>tableName</em>, projection, selection, selectionArgs,</p> <p><strong>null</strong>, <strong>null</strong>, sortOrder);</p> <p><strong>case</strong> <em>CONTACT</em>:</p> <p><strong>long</strong> id = ContentUris.<em>parseId</em>(uri);</p> <p>String where = "_id=" + id;</p> <p><strong>if</strong> (selection != <strong>null</strong> && !"".equals(selection)) {</p> <p>where = where + " and " + selection;</p> <p>}</p> <p><strong>return</strong> db.query(<em>tableName</em>, projection, where, selectionArgs, <strong>null</strong>,</p> <p><strong>null</strong>, sortOrder);</p> <p><strong>default</strong>:</p> <p><strong>throw</strong> <strong>new</strong> IllegalArgumentException("Uri IllegalArgument:" + uri);</p> <p>}</p> <p>}</p> <p>@Override</p> <p><strong>public</strong> <strong>int</strong> update(Uri uri, ContentValues values, String selection,</p> <p>String[] selectionArgs) {</p> <p>SQLiteDatabase db = <strong>this</strong>.openHelper.getWritableDatabase();</p> <p><strong>int</strong> result;</p> <p><strong>switch</strong> (<em>uriMatcher</em>.match(uri)) {</p> <p><strong>case</strong> <em>CONTACT_LIST</em>:</p> <p>result = db.update(selection, values, selection, selectionArgs);</p> <p><strong>break</strong>;</p> <p><strong>case</strong> <em>CONTACT</em>:</p> <p><strong>long</strong> id = ContentUris.<em>parseId</em>(uri);</p> <p>String where = "_id=" + id;</p> <p><strong>if</strong> (selection != <strong>null</strong> && !"".equals(selection)) {</p> <p>where = where + " and " + selection;</p> <p>}</p> <p>result = db.update(<em>tableName</em>, values, where, selectionArgs);</p> <p><strong>break</strong>;</p> <p><strong>default</strong>:</p> <p><strong>throw</strong> <strong>new</strong> IllegalArgumentException("Uri IllegalArgument:" + uri);</p> <p>}</p> <p><strong>return</strong> result;</p> <p>}</p> <p>}</p> <p><strong>2.</strong><strong>添加ContentProvider配置</strong></p> <p><provider android:name=<em>".provider.ContactContentProvider"</em> android:authorities=<em>"com.changcheng.sqlite.provider.contactprovider"</em>/></p> <p><strong>3.</strong><strong>测试SQLite示例程序的ContentProvider</strong></p> <p>ContentProvider即然是提供给其他应用访问本应用数据的,所以我们需要另创建一个Android应用,来测试SQLite示例程序的ContentProvider。我在此只列出query的测试方法testQuery:</p> <p><strong>public</strong> <strong>void</strong> testQuery() <strong>throws</strong> Throwable {</p> <p>ContentResolver contentResolver = <strong>this</strong>.getContext()</p> <p>.getContentResolver();</p> <p>Uri uri = Uri</p> <p>.<em>parse</em>("content://com.changcheng.sqlite.provider/contact");</p> <p>Cursor cursor = contentResolver.query(uri, <strong>new</strong> String[] { "_id",</p> <p>"name", "phone" }, <strong>null</strong>, <strong>null</strong>, "_id desc");</p> <p><strong>while</strong> (cursor.moveToNext()) {</p> <p>Log.<em>i</em>(<em>TAG</em>, "_id=" + cursor.getInt(0) + ",name="</p> <p>+ cursor.getString(1) + ",phone=" + cursor.getString(2));</p> <p>}</p> <p>}</p>

转载地址:http://wcaji.baihongyu.com/

你可能感兴趣的文章
安装k8s Master高可用集群
查看>>
忽略图片透明区域的事件(Flex)
查看>>
Xpath使用方法
查看>>
移动端自动化测试-Mac-IOS-Appium环境搭建
查看>>
Selenium之前世今生
查看>>
Selenium-WebDriverApi接口详解
查看>>
Selenium-ActionChains Api接口详解
查看>>
Selenium-Switch与SelectApi接口详解
查看>>
Selenium-Css Selector使用方法
查看>>
Linux常用统计命令之wc
查看>>
Java.nio
查看>>
Spring JTA应用之JOTM配置
查看>>
spring JdbcTemplate 的若干问题
查看>>
Servlet和JSP的线程安全问题
查看>>
PHP那点小事--三元运算符
查看>>
fastcgi_param 详解
查看>>
Linux中的进程
查看>>
学习python(1)——环境与常识
查看>>
学习设计模式(3)——单例模式和类的成员函数中的静态变量的作用域
查看>>
自然计算时间复杂度杂谈
查看>>