博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
android学习笔记54——ContentProvider
阅读量:4598 次
发布时间:2019-06-09

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

ContentProvider

ContentProvider用于实现数据共享.

ContentProvider是不同应用程序之间进行数据交换的标准API,其以某种Uri的形式对外提供数据,允许其他应用程序访问或修改数据;

其他应用程序使用ContentResolver根据Uri去访问操作指定数据。

注意:ContentProvider为android四大组件之一,需要在AndroidMainfest.xml中做配置处理。

如果把ContentProvider当做一个网站,那么完成的开发一个ContentProvider的操作步骤如下:

1.定义自己的ContentProvider类,该类需要继承android提供的ContentProvider基类;

2.向android系统注册这个“网站”,也就是在AndroidMainfest.xml文件中注册这个ContentProvider——就像注册Activity一样。注册ContentProvider需要为其绑定一个URL.

注意:

向android系统中注册ContentProvider只要在<application.../>元素中添加子元素即可,如下所示:

当我们向android系统注册了ContentProvider之后,其他应用程序就可通过Uri来访问DictProvider所暴露的数据了。

那么DictPovider到底如何暴露其提供的数据?

==》

由于应用程序对数据的操作无非就是CRUD,因此DictProvider除了需要继承ContentProvider之外,还需要提供如下几个方法:

public boolean onCreate()

该方法在ContentProvider创建后被调用,当其他应用程序第一次访问ContentProvider时,该ContentProvider会被创建出来,

并立即回调该onCreate()

public Uri insert(Uri uri,ContentValues values) 根据Uri插入values对应的数据
public int delete(Uri uri,String selection,String[] selecttionArgs) 根据Uri删除select条件所匹配的所有记录
publc int update(Uri uri,ContentValues values,String selection,Sting[] selecttionArgs) 根据Uri修改select条件所匹配的所有记录
public Cursor query(Uri uri,Sting[] projection,String selection,Sting[] selectionArgs,String sortOrder) 根据Uri查询select条件所匹配的所有记录,其中projection就是一个列名列表,表明只选择出指定的列的数据列
public String getType(Uri uri) 该方法用于返回当前Uri所代表的数据的MIME类型。如果该Uri对应数据可能包括多条记录,那么MIME类型字符串应该以vnd.android.cursor.dir/开头;如果该Uri对应的数据只包含一条记录,那么返回MIME类型字符串应该以vnd.android.cursor.item/开头

 

 

 

 

 

 

 

 

 

 

 

Uri简介

网页URL,如:https://www.baidu.com/s?tn=baidutop...

1.http://——URL协议部分,只要通过HTTP协议来访问网站,该部分为固定信息;

2.www.baidu.com——网站域名部分,只要通过http协议来访问网站,该部分总是固定信息;

3.s?tn=baidutop...——网站资源部分, 当访问者需要访问不同资源时,这个部分是动态改变的。

 

Android Uri因此类似,如下:

content://org.crazyit.providers.dictprovider/words

其也可分为三个部分:

1.content://,这个不是android规定的,是固定的;

2.org.crazyit.providers.dictprovider,这个部分就是ContentProvider的authority.系统就是由这个部分来找到操作那个ContentProvider.只要访问指定的ContentProvider,这个部分就是固定的;

3.words,资源部分或者说是数据部分,当访问者需要访问不同资源时,这个部分是动态改变的。

注意:

需要指出的是,Android的Uri所能表达的功能更丰富,还可以支持如下Uri:

content://org.crazyit.providers.dictprovider/words/2——此时需要访问的资源为words/2,其意味着访问words数据中ID为2的记录的word字段。

content://org.crazyit.providers.dictprovider/words——访问全部数据;

 

大部分使用ContentProvider所操作的数据都来自于数据库,但有时候这些数据也可以来自于文件、XML或网络等其他存储方式,此时支持的Uri也可改为如下形式:

content://org.crazyit.providers.dictprovider/word/detail/——代表操作word节点下的detail节点;

 

为了将一个字符串转换成Uri,Android提供的Uri工具类提供了parse()静态方法,转换方式如下:

Uri uri = Uri.parse("content://org.crazyit.providers.dictprovider/words/2");

 

使用ContentResolver操作数据

ContentProvider相当于一个“网站”,它的作用是暴露可供操作的数据;

其他程序则通过ContentResolver来操作ContentProvider所暴露的数据;ContentResolver相当于HttpClient.

Content提供了如下方法来获取ContentResolver对象:getContentResolver().

获取ContentResolver对象成功后,可通过如下方法操作数据:

insert(Uri uri,ContentValues values) 向Uri对应的ContentProvider中插入values对应的数据
delete(Uri uri,String where,Sting[] selectionArgs) 删除uri对应的ContentProvider中where提交匹配的数据
update(Uri uri,ContentValues values,String where,String[] selectionArgs) 更新uri对应的ContentProvider中where提交匹配的数据
query(Uri uri,Sting[] projection,String selection,String[] selectionArgs,String sortOrder) 查询Uri对应的ContentProvider中where提交匹配的数据

 

 

 

 

 

 

 注意:一般来说,ContentProvider是单实例模式的,当多个应用程序通过ContentResolver来操作ContentProvider提供的数据时,ContentResolver

调用的数据操作将会委托给同一个ContentProvider处理。

 

操作系统的ContentProvider

使用ContentProvider操作数据的操作步骤:

1.调用Activity的ContentResolver()获取ContentResolver对象

2.根据需要调用ContentResolver的insert()、delete()、update()、query方法操作数据即可

注意:操作系统提供的ContentResolver,需要了解其对应的ContentProvider对应的Uri.

 

使用ContentProvider管理联系人

Android系统提供了Contacts应用程序来管理联系人,而且Android系统还为联系人管理提供了ContentProvider,这就运行其他应用程序以ContentResolver来管理联系人数据。

Android系统对联系人管理ContentProvider的几个Uri如下:

ContactsContact.Contacts.CONTENT_URI 管理联系人的Uri
ContactsContact.CommonDataKinds.Phone.CONTENT_URI 管理联系人的电话的Uri
ContactsContact.CommonDataKinds.Email.CONTENT_URI 管理联系人的邮箱的Uri

 

 

 

 

实例如下:

布局文件main.xml==>
result.xml==>
AndroidMainfest.xml==>
代码实现==》package com.example.myprovidercontent1;import java.util.ArrayList;import android.os.Bundle;import android.provider.ContactsContract;import android.app.Activity;import android.app.AlertDialog;import android.database.Cursor;import android.database.DataSetObserver;import android.util.Log;import android.view.Gravity;import android.view.Menu;import android.view.View;import android.view.ViewGroup;import android.view.View.OnClickListener;import android.widget.AbsListView;import android.widget.AbsListView.LayoutParams;import android.widget.Button;import android.widget.ExpandableListAdapter;import android.widget.ExpandableListView;import android.widget.TextView;public class MainActivity extends Activity{ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btnQuery = (Button) this.findViewById(R.id.btnQuery); btnQuery.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { query(v); } }); } private void query(View v) { // 定义两个List封装系统联系人信息、指定联系人的电话号码、Email等... final ArrayList
names = new ArrayList
(); final ArrayList
> details = new ArrayList
>(); // 使用ContentResolver查找联系人数据 Cursor cursor = this.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null); // 遍历查询结果,获取系统中所有联系人 while (cursor.moveToNext()) { // 联系人Id、名称 String contactId = cursor.getString(cursor .getColumnIndex(ContactsContract.Contacts._ID)); String name = cursor.getString(cursor .getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); names.add(name); Log.i("swg", "name:" + name); // 联系人电话号码 Cursor phones = this.getContentResolver() .query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=" + contactId, null, null); final ArrayList
detail = new ArrayList
(); // 遍历查询结果,获取该联系人的多个 电话号码 while (phones.moveToNext()) { String phoneNum = phones.getString(phones .getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); Log.i("swg", "电话号码:" + phoneNum); detail.add("电话号码:" + phoneNum); } phones.close(); // 使用ContentResolver查询联系人Email Cursor emails = this.getContentResolver() .query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, null, ContactsContract.CommonDataKinds.Email.CONTACT_ID + "=" + contactId, null, null); // 遍历查询结果,获取该联系人的多个Email地址 while (emails.moveToNext()) { String emailAdd = emails.getString(emails .getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA)); Log.i("swg", "邮件地址:" + emailAdd); detail.add("邮件地址:" + emailAdd); } emails.close(); details.add(detail); } cursor.close(); // 加载result.xml界面布局文件 View resultDialog = this.getLayoutInflater().inflate(R.layout.result, null); ExpandableListView list = (ExpandableListView) resultDialog.findViewById(R.id.list); // 创建一个ExpandableListAdapter对象 ExpandableListAdapter adapter = new ExpandableListAdapter() { @Override public void unregisterDataSetObserver(DataSetObserver observer) { } @Override public void registerDataSetObserver(DataSetObserver observer) { } @Override public void onGroupExpanded(int groupPosition) { } @Override public void onGroupCollapsed(int groupPosition) { } @Override public boolean isEmpty() { return false; } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { return true; } @Override public boolean hasStableIds() { return true; } // 该方法决定每个组选项的外观 @Override public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { TextView tv = getTextView(); tv.setText(getGroup(groupPosition).toString()); return tv; } @Override public long getGroupId(int groupPosition) { return groupPosition; } @Override public int getGroupCount() { // details return names.size(); } @Override public Object getGroup(int groupPosition) { // details return names.get(groupPosition); } @Override public long getCombinedGroupId(long groupId) { return 0; } @Override public long getCombinedChildId(long groupId, long childId) { return 0; } @Override public int getChildrenCount(int groupPosition) { return details.get(groupPosition).size(); } private TextView getTextView() { AbsListView.LayoutParams lp = new LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, 64); TextView tv = new TextView(MainActivity.this); tv.setLayoutParams(lp); tv.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.LEFT); tv.setPadding(36, 0, 0, 0); tv.setTextSize(20); return tv; } // 该方法决定每个子项的外观 @Override public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { TextView tv = getTextView(); tv.setText(getChild(groupPosition, childPosition).toString()); return tv; } @Override public long getChildId(int groupPosition, int childPosition) { return childPosition; } @Override public Object getChild(int groupPosition, int childPosition) { return details.get(groupPosition).get(childPosition); } @Override public boolean areAllItemsEnabled() { return false; } }; // 为ExpandableListView设置Adapter list.setAdapter(adapter); // 使用对话框来显示查询结果 new AlertDialog.Builder(MainActivity.this).setView(resultDialog) .setPositiveButton("确定", null).show(); }}

 实例二、添加联系人

 

转载于:https://www.cnblogs.com/YYkun/p/5981382.html

你可能感兴趣的文章
Python 和其他编程语言数据类型的比较
查看>>
T2695 桶哥的问题——送桶 题解
查看>>
HTML5 表单
查看>>
Android群英传》读书笔记 (3) 第六章 Android绘图机制与处理技巧 + 第七章 Android动画机制与使用技巧...
查看>>
OLEDB和ODBC的区别(优缺点)
查看>>
关于微信公众平台测试号配置失败的问题
查看>>
CLR执行模块基础
查看>>
【NOIP2001】统计单词个数
查看>>
linux常用端口
查看>>
异常处理
查看>>
/proc/uptime详解
查看>>
如何建立合适的索引?
查看>>
acwing 651. 逛画展
查看>>
(待完成)qbxt2019.05 总结12 - 趣味题目 鹰蛋
查看>>
[2018/11/18] Java数据结构(2) 简单排序 冒泡排序 选择排序 插入排序
查看>>
关于WPF程序只运行一个实例的方法
查看>>
游标的使用
查看>>
图论:点分治
查看>>
mysql
查看>>
C/C++ 知识点---sizeof使用规则及陷阱分析(网摘)
查看>>