Android笔记(五十六) Android四大组件之一——ContentProvider,实现自己的ContentProvider
有时候我们自己的程序也需要向外接提供数据,那么就需要我们自己实现ContentProvider。
自己实现ContentProvider的话需要新建一个类去继承ContentProvider,然后重写类中的的6个抽象方法。
onCreate():初始化内容提供器时候会调用,通常会在这里完成对数据库的创建和升级等操作,返回true表示内容提供器初始化成功,返回false则表示失败,注意,只有当存在ContentResolver尝试访问我们程序中的数据时,内容提供其才会被初始化
query():从内容提供其中查询数据,使用uri参数来确定查询哪张表,projection参数用于确定查询哪些列,selection和selectionArgs参数用于约束查询哪些行,sortOrder参数用于对结果进行排序,查询结果存放在Cursor对象中返回。
insert():向内容提供器中添加一条数据,使用uri参数来确定要添加到的表,待添加的数据保存在values参数中,添加完成后,返回一个用于表示这条新记录的URI。
update():更新内容提供器中已有的数据,使用uri参数来确定更新哪一张表中的数据,新数据保存在values参数中,selection和selectionArgs参数用于约束更新哪些列,受影响的行数将作为返回值返回。
delete():从内容提供其中删除数据,使用uri参数来确定删除哪一张表中的数据,selection和selectionArgs参数用于约束删除哪些行,被删除的行数将作为返回值返回。
getType():根据传入的内容URI来返回相应的MIME类型。
可以看到,几乎每一个方法都会带有Uri这个参数,这个参数也正是调用ContentResolver的增删改查方法时传递过来的,而现在,我们需要对传入的Uri参数进行解析,从中分析出调用方期待访问的表和数据。
一般的标准的内容URI写法是这样的
content://com.example.app.provider/table1
这就表示调用方期待访问的是com.example.app这个应用的table1表中的数据。除此之外,我们还可以在这个内容URI的后面加上一个id,例如
content://com.example.app.provider/table1/1
这就表示调用方期待访问的是com.example.app这个应用的table1表中的id为1的数据。
内容URI的格式主要就只有以上两种,以路径结尾就表示期望访问该表中所有的数据,以id结尾就表示期望访问该表中拥有相应的id的数据,我们可以使用通配符的方式来分别匹配这两种格式的内容URI,规则如下
1.*表示匹配任意长度的任意字符
2.#表示匹配任意长度的数据
所以一个能够匹配任意表的内容URI格式就可以写成:
content://com.example.app.provider/*
而一个能够匹配table1表中任意一行数据的内容URI格式就可以写成
content://com.example.app.provider/table1/#
接着我们再借助UriMatcher这个类就可以轻松的实现匹配内容URI的功能,UriMatcher中提供了一个addURI()方法,这个方法接收三个参数,可以分别把权限,路径和一个自定义代码传递进去,这样,当调用UriMatcher的match()方法时,就可以将一个Uri对象传入,返回值是某个能够匹配这个Uri对象所对应的自定义代码,利用这个代码,我们就可以判断出调用方期待访问的是哪张表中的数据了。
除此之外,还有一个getTypt()方法,它是所有的内容提供其都必须提供的一个方法,用于获取Uri对象所对应的MIME类型,一个内容URI所对应的MIME字符串主要由三部分组成,Android对这三个部分做了如下格式规定:
1.必须以vnd开头
2.如果内容URI以路径结尾,则后面接android.cursor.dir/,如果内容URI以id结尾,则后接android.cursor.item/。
3.最后接上vnd.<authority>.<path>
简单示例:
MyContentProvider
MyContentProvider.java
- package cn.lixyz.mycontentprovider;
- import android.content.ContentProvider;
- import android.content.ContentValues;
- import android.content.Context;
- import android.content.UriMatcher;
- import android.database.Cursor;
- import android.database.sqlite.SQLiteDatabase;
- import android.database.sqlite.SQLiteDatabase.CursorFactory;
- import android.database.sqlite.SQLiteOpenHelper;
- import android.net.Uri;
- public class MyContentProvider extends ContentProvider {
- public static final int STUDENTS_DIR = 0;
- public static final int STUDENTS_ITEM = 1;
- public static final int CLASSES_DIR = 2;
- public static final int CLASSES_ITEM = 3;
- private static UriMatcher uriMatcher;
- private MyDBHelper myDBHelper;
- private SQLiteDatabase database;
- private static final String AUTHORITY = "cn.lixyz.mycontentprovider.cp";
- static {
- uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
- uriMatcher.addURI("cn.lixyz.mycontentprovider.cp", "students", STUDENTS_DIR);
- uriMatcher.addURI("cn.lixyz.mycontentprovider.cp", "students/#", STUDENTS_ITEM);
- uriMatcher.addURI("cn.lixyz.mycontentprovider.cp", "classes", CLASSES_DIR);
- uriMatcher.addURI("cn.lixyz.mycontentprovider.cp", "classes/#", CLASSES_ITEM);
- }
- @Override
- public boolean onCreate() {
- myDBHelper = new MyDBHelper(getContext(), "school.db", null, 1);
- return true;
- }
- @Override
- public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
- database = myDBHelper.getReadableDatabase();
- Cursor cursor = null;
- switch (uriMatcher.match(uri)) {
- case STUDENTS_DIR:
- cursor = database.query("students", projection, selection, selectionArgs, null, null, sortOrder);
- break;
- case STUDENTS_ITEM:
- String studentID = uri.getPathSegments().get(1);
- cursor = database.query("students", projection, "_id=?", new String[] { studentID }, null, null, sortOrder);
- break;
- case CLASSES_DIR:
- cursor = database.query("classes", projection, selection, selectionArgs, null, null, sortOrder);
- break;
- case CLASSES_ITEM:
- String classID = uri.getPathSegments().get(1);
- cursor = database.query("classes", projection, "_id=?", new String[] { classID }, null, null, sortOrder);
- break;
- }
- return cursor;
- }
- @Override
- public String getType(Uri uri) {
- switch (uriMatcher.match(uri)) {
- case STUDENTS_DIR:
- return "vnd.android.cursor.dir/vnd.cn.lixyz.mycontentprovider.cp.students";
- case STUDENTS_ITEM:
- return "vnd.android.cursor.item/vnd.cn.lixyz.mycontentprovider.cp.students";
- case CLASSES_DIR:
- return "vnd.android.cursor.dir/vnd.cn.lixyz.mycontentprovider.cp.classes";
- case CLASSES_ITEM:
- return "vnd.android.cursor.item/vnd.cn.lixyz.mycontentprovider.cp.classes";
- }
- return null;
- }
- @Override
- public Uri insert(Uri uri, ContentValues values) {
- database = myDBHelper.getWritableDatabase();
- Uri returnUri = null;
- switch (uriMatcher.match(uri)) {
- case STUDENTS_DIR:
- case STUDENTS_ITEM:
- long newStudent = database.insert("students", null, values);
- returnUri = Uri.parse("content://" + AUTHORITY + "/students/" + newStudent);
- break;
- case CLASSES_DIR:
- case CLASSES_ITEM:
- long newClass = database.insert("classes", null, values);
- returnUri = Uri.parse("content://" + AUTHORITY + "/classes/" + newClass);
- break;
- }
- return returnUri;
- }
- @Override
- public int delete(Uri uri, String selection, String[] selectionArgs) {
- // TODO Auto-generated method stub
- return 0;
- }
- @Override
- public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
- // TODO Auto-generated method stub
- return 0;
- }
- class MyDBHelper extends SQLiteOpenHelper {
- private Context mContext;
- public MyDBHelper(Context context, String name, CursorFactory factory, int version) {
- super(context, name, factory, version);
- this.mContext = context;
- }
- @Override
- public void onCreate(SQLiteDatabase db) {
- db.execSQL(
- "create table if not exists students (_id integer primary key autoincrement,studentName text,studentAge integer,class text)");
- db.execSQL("create table if not exists classes (_id integer primary key autoincrement,className text)");
- }
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- // TODO Auto-generated method stub
- }
- }
- }
AndroidManifest.xml
- <provider
- android:name="MyContentProvider"
- android:authorities="cn.lixyz.mycontentprovider.cp"
- android:exported="true" >
- </provider>
MyContentResolver
MainActivity.java
- package cn.lixyz.mycontentresolver;
- import android.app.Activity;
- import android.content.ContentResolver;
- import android.content.ContentValues;
- import android.database.Cursor;
- import android.net.Uri;
- import android.os.Bundle;
- import android.util.Log;
- import android.view.View;
- import android.widget.Button;
- import android.widget.EditText;
- public class MainActivity extends Activity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- initView();
- }
- public void clickButton(View view) {
- switch (view.getId()) {
- case R.id.bt_addclass:
- addClass();
- break;
- case R.id.bt_addstudent:
- addStudent();
- break;
- case R.id.searchclass:
- searchClass();
- break;
- case R.id.searchstudent:
- searchStrudent();
- break;
- }
- }
- // 搜索学生方法
- private void searchStrudent() {
- Uri uri = Uri.parse("content://cn.lixyz.mycontentprovider.cp/students");
- ContentResolver contentResolver = getContentResolver();
- Cursor cursor = contentResolver.query(uri, null, null, null, null);
- if (cursor != null) {
- cursor.moveToFirst();
- while (cursor.moveToNext()) {
- String tudentName = cursor.getString(cursor.getColumnIndex("studentName"));
- int studentAge = cursor.getInt(cursor.getColumnIndex("studentAge"));
- String className = cursor.getString(cursor.getColumnIndex("class"));
- Log.d("TTTT", "学生姓名:" + tudentName + ",年龄 : " + studentAge + ",所在班级:" + className);
- }
- }
- }
- // 搜索班级方法
- private void searchClass() {
- Uri uri = Uri.parse("content://cn.lixyz.mycontentprovider.cp/classes");
- ContentResolver contentResolver = getContentResolver();
- Cursor cursor = contentResolver.query(uri, null, null, null, null);
- if (cursor != null) {
- cursor.moveToFirst();
- while (cursor.moveToNext()) {
- String className = cursor.getString(cursor.getColumnIndex("className"));
- Log.d("TTTT", "班级:" + className);
- }
- }
- }
- // 添加学生方法
- private void addStudent() {
- String studentName = et_studentname.getText().toString().trim();
- String studentAge = et_studentage.getText().toString().trim();
- String studentClass = et_studentclass.getText().toString().trim();
- Uri uri = Uri.parse("content://cn.lixyz.mycontentprovider.cp/students");
- ContentResolver contentResolver = getContentResolver();
- ContentValues cv = new ContentValues();
- cv.put("studentName", studentName);
- cv.put("studentAge", studentAge);
- cv.put("class", studentClass);
- Uri returnUri = contentResolver.insert(uri, cv);
- Log.d("TTTT", "returnUri:" + returnUri.toString());
- }
- // 添加班级方法
- private void addClass() {
- ContentResolver contentResolver = getContentResolver();
- Uri uri = Uri.parse("content://cn.lixyz.mycontentprovider.cp/classes");
- String className = et_addclass.getText().toString().trim();
- ContentValues cv = new ContentValues();
- cv.put("className", className);
- contentResolver.insert(uri, cv);
- }
- private EditText et_addclass, et_studentname, et_studentage, et_studentclass;
- private Button bt_addclass, bt_addstudent, searchclass, searchstudent;
- private void initView() {
- et_addclass = (EditText) findViewById(R.id.et_addclass);
- et_studentname = (EditText) findViewById(R.id.et_studentname);
- et_studentage = (EditText) findViewById(R.id.et_studentage);
- et_studentclass = (EditText) findViewById(R.id.et_studentclass);
- bt_addclass = (Button) findViewById(R.id.bt_addclass);
- bt_addstudent = (Button) findViewById(R.id.bt_addstudent);
- searchclass = (Button) findViewById(R.id.searchclass);
- searchstudent = (Button) findViewById(R.id.searchstudent);
- }
- }
activity_main.xml
- <LinearLayout 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"
- android:orientation="vertical"
- android:paddingBottom="@dimen/activity_vertical_margin"
- android:paddingLeft="@dimen/activity_horizontal_margin"
- android:paddingRight="@dimen/activity_horizontal_margin"
- android:paddingTop="@dimen/activity_vertical_margin"
- tools:context="cn.lixyz.mycontentresolver.MainActivity" >
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="添加班级" />
- <EditText
- android:id="@+id/et_addclass"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:hint="输入班级名称" />
- <Button
- android:id="@+id/bt_addclass"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:onClick="clickButton"
- android:text="添 加" />
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="添加学生" />
- <EditText
- android:id="@+id/et_studentname"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:hint="输入学生姓名" />
- <EditText
- android:id="@+id/et_studentage"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:hint="输入学生年龄" />
- <EditText
- android:id="@+id/et_studentclass"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:hint="输入学生班级" />
- <Button
- android:id="@+id/bt_addstudent"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:onClick="clickButton"
- android:text="添 加" />
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="搜索" />
- <Button
- android:id="@+id/searchclass"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:onClick="clickButton"
- android:text="点我搜索班级" />
- <Button
- android:id="@+id/searchstudent"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:onClick="clickButton"
- android:text="点我搜索学生" />
- </LinearLayout>
这样,就可以在ContentResolver应用中,对ContentProvider应用的数据库进行insert和query操作了。
Android笔记(五十六) Android四大组件之一——ContentProvider,实现自己的ContentProvider的更多相关文章
- Android笔记(七十六) 点菜DEMO
一个朋友让看一下他的代码,一个点菜的功能,他和我一样,初学者,代码比我的都混乱,也是醉了,干脆想着自己写个demo给他看,原本想着听简单,半个小时应该就可以搞定,真正写的时候,画了3h+,汗颜... ...
- Android笔记(十六) 简易计算器
实现功能: 简单计算器 布局及美化 采用LinearLayout嵌套LinearLayout实现布局. 要求 1. 按钮所有文字居于右下角 2. 按钮为白色,点击变成橘色 3. 显示屏文字居右显示并且 ...
- Android笔记二十四.Android基于回调的事件处理机制
假设说事件监听机制是一种托付式的事件处理,那么回调机制则与之相反,对于基于回调的事件处理模型来说,事件源和事件监听器是统一的,或者说事件监听器全然消失了,当用户在GUI控件上激发某个事件时,控 ...
- Android笔记(十) Android中的布局——表格布局
TableLayout运行我们使用表格的方式来排列控件,它的本质依然是线性布局.表格布局采用行.列的形式来管理控件,TableLayout并不需要明确的声明包含多少行多少列,而是通过添加TableRo ...
- Android之旅十六 android中各种资源的使用
android中各种资源的使用: 在android开发中,各种资源的合理使用应该在各自的xml中进行定义,以便反复使用; 字符串资源:strings.xml,xml中引用:@string/XXX,ja ...
- 论文阅读笔记五十六:(ExtremeNet)Bottom-up Object Detection by Grouping Extreme and Center Points(CVPR2019)
论文原址:https://arxiv.org/abs/1901.08043 github: https://github.com/xingyizhou/ExtremeNet 摘要 本文利用一个关键点检 ...
- Android实训案例(六)——四大组件之一BroadcastReceiver的基本使用,拨号,短信,SD卡,开机,应用安装卸载监听
Android实训案例(六)--四大组件之一BroadcastReceiver的基本使用,拨号,短信,SD卡,开机,应用安装卸载监听 Android中四大组件的使用时重中之重,我这个阶段也不奢望能把他 ...
- Nodejs学习笔记(十六)--- Pomelo介绍&入门
目录 前言&介绍 安装Pomelo 创建项目并启动 创建项目 项目结构说明 启动 测试连接 聊天服务器 新建gate和chat服务器 配置master.json 配置servers.json ...
- Nodejs学习笔记(十六)—Pomelo介绍&入门
前言&介绍 Pomelo:一个快速.可扩展.Node.js分布式游戏服务器框架 从三四年前接触Node.js开始就接触到了Pomelo,从Pomelo最初的版本到现在,总的来说网易出品还算不错 ...
- 微信小程序把玩(十六)form组件
原文:微信小程序把玩(十六)form组件 form表单组件 是提交form内的所有选中属性的值,注意每个form表单内的组件都必须有name属性指定否则提交不上去,button中的type两个subm ...
随机推荐
- 不规则的Ifc构件顶点提取方法
BIM模型中有很多不规则的构件,在IFC中这些不规则的构件一般用顶点的形式表示,顶点坐标提取路径: IfcObject->IfcProductDefinitionShape->IfcSh ...
- sysfile20191122
ass_s_ccp_ft:-108; ass_s_ccp_all:-108; ass_tag_ft:-105; ass_tag_all:-105; rept_port:9000; Q_value:0. ...
- SDN实验---Ryu的安装
一:Ryu是主流SDN开源控制器之一 (一)推文(摘录自) https://ryu.readthedocs.io/en/latest/ https://www.sdnlab.com/1785.html ...
- 用Vue2.0实现简单的分页及跳转
用Vue2.0实现简单的分页及跳转 2018年07月26日 20:29:51 Freya_yyy 阅读数 3369 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog ...
- Jenkins - 构建流水线
1 - 以流水线的方式进行构建 关联多任务形成流水线的两种方法 通过定义项目的后续项目,将项目直接关联起来按顺序执行, 另外定义一个用于统筹管理的项目,定义各项目之间的关联性,然后以流水线的方式执行 ...
- Tomcat启动原理/使用tomcat的应用是如何从tomcat的main函数开始运行的
从main方法开始打断点,逐步调试,了解程序运行过程 全局唯一的public static void main(String[] args)main Springboot* 内置tomcat,开发的时 ...
- 转载:Python Web开发最难懂的WSGI协议,到底包含哪些内容?
原文:PSC推出的第二篇文章-<Python Web开发最难懂的WSGI协议,到底包含哪些内容?>-2017.9.27 我想大部分Python开发者最先接触到的方向是WEB方向(因为总是有 ...
- AutoResetEvent 学生考试,老师阅卷,学生等待考试结果
class Program { static void Main(string[] args) { )); t.Start(); Console.WriteLine("老师等待提交试卷&qu ...
- IDEA修改Servlet的代码生成模板
file--->settings,打开settings面板
- C++的派生类构造函数是否要带上基类构造函数
//public:Student(int s_age):People(s_age) //C++的派生类构造函数后面是否带上基类构造函数,取决于基类构造函数是否需要传入参数,如果要参数,就一定带上:不需 ...