Xamarin.Android开发实践(十二)

简介: 原文:Xamarin.Android开发实践(十二) Xamarin.Android之ContentProvider 一、前言 掌握了如何使用SQLiteOpenHelper之后,我们就可以进行下一步的学习。

原文:Xamarin.Android开发实践(十二)

Xamarin.Android之ContentProvider

一、前言

掌握了如何使用SQLiteOpenHelper之后,我们就可以进行下一步的学习。本章我们将会学习如何使用ContentProvider来将数据库方面的操作封装起来,同时它还可以供其他应用访问并操作数据库。

 

二、概念

首先我们不会急于写代码,而是要搞懂如何利用ContentProvider对数 据库进行操作,因为我们不会直接操作数据库对象,而是通过URI来操作数据库。这就好比你要获取User表的全部内容,那么这个URI就是 content://base/user其中base是自己命名的,最好是能够唯一。因为我们需要依靠这个区分数据库,然后就是user是用来区分操作的 是哪个表,当然你也可以不用命名为user可以是其他的名称,最终反正要依靠代码去判断的。这样我们就可以避免在活动中直接对数据库对象操作,也方便对数 据库进行统一的维护。

 

三、实际操作

 

1、搭建基本框架

新建一个LocationContentProvider类,并且继承自ContentProvider,还要重写该类的OnCreateDeleteGetTypeInsertQueryUpdate方法。

 

2、设计数据库以及URI

下面是笔者设计好的结构:

 1 public static string PROVIDER_NAME = "xamarin-cn.location";  2  3 private const string DATABASE_NAME = "location";  4 private const int DATABASE_VERSION = 1;  5  6 private const string USERTABLE_NAME = "tuser";  7 private const int USER = 1;  8 private const int USER_ID = 2;  9 private static IDictionary<string, string> userProjectionMap; 10 public class UserTable 11 { 12 public static Android.Net.Uri CONTENT_URI = Android.Net.Uri.Parse("content://" + PROVIDER_NAME + "/user"); 13 public const string _ID = "_id"; 14 public const string UserName = "username"; 15 public const string UserPwd = "userpwd"; 16 public const string Age = "age"; 17 }

 其中 PROVIDER_NAME 是URI的基址,DATABASE_NAMEDATABASE_VERSION是数据库的命名的和版本号,下面就是tuser表的信息,分别是表名、URI标识1、URI标识2、表结构键值对。UserTable类中的就是该表公开的属性,其中包含表的字段以及查询该表的URI路径。我们可以看到该表的URI路径为content://xamarin-cn.location/user

 

3、初始化UriMatcher

我们需要通过UriMatcher这个类来判断URI操作的是哪个数据库的哪个表,这样就不需要我们自己通过字符串进行判断,具体的初始化可以见如下代码:

 1         private static UriMatcher uriMatcher;
 2         static LocationContentProvider()  3  {  4 userProjectionMap = new Dictionary<string, string>();  5  userProjectionMap.Add(UserTable._ID, UserTable._ID);  6  userProjectionMap.Add(UserTable.UserName, UserTable.UserName);  7  userProjectionMap.Add(UserTable.UserPwd, UserTable.UserPwd);  8  userProjectionMap.Add(UserTable.Age, UserTable.Age);  9 uriMatcher = new UriMatcher(UriMatcher.NoMatch); 10 uriMatcher.AddURI(PROVIDER_NAME, "user", USER); 11 uriMatcher.AddURI(PROVIDER_NAME, "user/#", USER_ID); 12 }

 这里我们通过UriMatcherAddURI方法添加的不同类型URI,其中有针对整张表的,还有针对表中某条数据的。

 

4、建立数据库

这里我就不一一介绍了直接放出代码:

 1         private LocationSqliteOpenHelper dbHelper;
 2         class LocationSqliteOpenHelper : SQLiteOpenHelper  3  {  4 public LocationSqliteOpenHelper(Context context)  5 : base(context, DATABASE_NAME, null, DATABASE_VERSION)  6  {  7  }  8  9 public override void OnCreate(SQLiteDatabase db) 10  { 11 StringBuilder strSql = new StringBuilder(); 12 strSql.AppendFormat("CREATE TABLE {0} (", USERTABLE_NAME); 13 strSql.AppendFormat("{0} INTEGER PRIMARY KEY NOT NULL,", UserTable._ID); 14 strSql.AppendFormat("{0} TEXT NOT NULL,", UserTable.UserName); 15 strSql.AppendFormat("{0} TEXT NOT NULL,", UserTable.UserPwd); 16 strSql.AppendFormat("{0} INTEGER NOT NULL)", UserTable.Age); 17  db.ExecSQL(strSql.ToString()); 18  } 19 20 public override void OnUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 21  { 22 db.ExecSQL("DROP TABLE IF EXISTS " + USERTABLE_NAME); 23  OnCreate(db); 24  } 25 }

 

 

5.初始化ContentProvider

首先我们需要在OnCreate方法中将dbHelper初始化:

1 public override bool OnCreate()
2 { 3 dbHelper = new LocationSqliteOpenHelper(Context); 4 return true; 5 }

 

 

6.完善Query方法

为了能够方便的组织查询语句这里笔者使用了SQLiteQueryBuilder对象来组织,下面就是查询的代码:

 1         public override Android.Database.ICursor Query(Android.Net.Uri uri, string[] projection, string selection, string[] selectionArgs, string sortOrder)  2  {  3 SQLiteQueryBuilder qb = new SQLiteQueryBuilder();  4 qb.Tables = USERTABLE_NAME;  5 //根据uri判断查询的是某条数据还是针对整个表,从而决定条件语句  6 switch (uriMatcher.Match(uri))  7  {  8 case USER:  9  { 10 //设置需要获取的字段 11 //userProjectionMap默认包含的所有字段 12  qb.SetProjectionMap(userProjectionMap); 13  } 14 break; 15 case USER_ID: 16  { 17  qb.SetProjectionMap(userProjectionMap); 18 //拼接条件语句 19 //其中uri.PathSegments.ElementAt(1) 将会获取第二个片段, 20 //就是第二个“/”后台的内容,如果后面还存在“/”则获取他们之间的内容 21 qb.AppendWhere(UserTable._ID + "=" + uri.PathSegments.ElementAt(1)); 22  } 23 break; 24  } 25 SQLiteDatabase db = dbHelper.ReadableDatabase; 26 ICursor c = qb.Query(db, projection, selection, selectionArgs, null, null, " _id desc"); 27  c.SetNotificationUri(Context.ContentResolver, uri); 28 return c; 29 }

 代码中的注释已经将重点部分都介绍了,关于Query的参数可以跟数据库对象的Query进行比较,都是一样的只是少了一部分参数。

 

7.完善Insert

因为SQLite规定了id只能是数据库自动生成的,所以在插入数据库这块只需要判断操作的是哪个表,介于笔者这里只有一个表所以没有该项操作,下面是具体的代码:

1         public override Android.Net.Uri Insert(Android.Net.Uri uri, ContentValues values)
2  { 3 SQLiteDatabase db = dbHelper.WritableDatabase; 4 long rowId = db.Insert(USERTABLE_NAME, null, values); 5 //拼接最终形成的URI 6 Android.Net.Uri result = ContentUris.WithAppendedId(UserTable.CONTENT_URI, rowId); 7 Context.ContentResolver.NotifyChange(result, null); 8 return result; 9 }

唯一要说明的就是在添加完数据之后要将这条数据组成的uri返回,这样就可以方便以后的查询。

 

8.完善Update

 1         public override int Update(Android.Net.Uri uri, ContentValues values, string selection, string[] selectionArgs)  2  {  3 SQLiteDatabase db = dbHelper.WritableDatabase;  4 int count = 0;  5 switch (uriMatcher.Match(uri))  6  {  7 case USER:  8  {  9 count = db.Update(USERTABLE_NAME, values, selection, selectionArgs); 10  } 11 break; 12 case USER_ID: 13  { 14 String userid = uri.PathSegments.ElementAt(1); 15 string select = ""; 16 //如果还有附加的查询语句则拼接上去 17 if (selection != null) 18 select = " AND(" + selection + ")"; 19 count = db.Update(USERTABLE_NAME, values, UserTable._ID + "=" + userid + select, selectionArgs); 20  } 21 break; 22  } 23 Context.ContentResolver.NotifyChange(uri, null); 24 return count; 25 }

这里跟查询一样,需要判断是针对某条数据还是整个表。

 

9.完善Delete

理解了Update,删除就简单了,只是将db.Update方法改写成Delete即可,代码如下所示:

 1         public override int Delete(Android.Net.Uri uri, string selection, string[] selectionArgs)  2  {  3 SQLiteDatabase db = dbHelper.WritableDatabase;  4 int count = 0;  5 switch (uriMatcher.Match(uri))  6  {  7 case USER:  8  {  9 count = db.Delete(USERTABLE_NAME, selection, selectionArgs); 10  } 11 break; 12 case USER_ID: 13  { 14 String userid = uri.PathSegments.ElementAt(1); 15 string select = ""; 16 if (selection != null) 17 select = " AND(" + selection + ")"; 18 count = db.Delete(USERTABLE_NAME, 19 UserTable._ID + "=" + userid + select, 20  selectionArgs); 21  } 22 break; 23  } 24 Context.ContentResolver.NotifyChange(uri, null); 25 return count; 26 }

 最后就是GetType方法,只要返回空字符串即可。

 

四、操作ContentProvider

现在我们回到MainActivity中使用ContentProvider对数据库进行操作,其中最关键的是ContentResolver是不是跟ContentProvider是配对的?通过ContentResolver我们就可以通过URI来操作数据库,而不需要关注具体的数据库对象,比如下面的代码我们进行了插入、查询、更新和删除操作,代码量要比使用SQLiteOpenHelper更少,同时也便于后期的维护:

 1             ContentValues values = new ContentValues();
 2             values.Put(LocationContentProvider.UserTable.UserName, "yzf");  3 values.Put(LocationContentProvider.UserTable.UserPwd, "123");  4 values.Put(LocationContentProvider.UserTable.Age, 23);  5 Android.Net.Uri uri = ContentResolver.Insert(LocationContentProvider.UserTable.CONTENT_URI, values);  6  7 var c = ContentResolver.Query(uri, null, null, null, null);  8  c.MoveToFirst();  9 string username = c.GetString(c.GetColumnIndex(LocationContentProvider.UserTable.UserName)); 10 11  values.Clear(); 12 values.Put(LocationContentProvider.UserTable.UserName, "zn"); 13 ContentResolver.Update(uri, values, null, null); 14 15 c = ContentResolver.Query(uri, null, null, null, null); 16  c.MoveToFirst(); 17 username = c.GetString(c.GetColumnIndex(LocationContentProvider.UserTable.UserName)); 18 19 ContentResolver.Delete(uri, null, null);

 

目录
相关文章
|
3月前
|
开发框架 前端开发 Android开发
安卓与iOS开发中的跨平台策略
在移动应用开发的战场上,安卓和iOS两大阵营各据一方。随着技术的演进,跨平台开发框架成为开发者的新宠,旨在实现一次编码、多平台部署的梦想。本文将探讨跨平台开发的优势与挑战,并分享实用的开发技巧,帮助开发者在安卓和iOS的世界中游刃有余。
|
2天前
|
JavaScript 搜索推荐 Android开发
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
22 8
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
|
14天前
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
115 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
12天前
|
Dart 前端开发 Android开发
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
35 4
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
28天前
|
缓存 前端开发 Android开发
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
76 12
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
|
1月前
|
Dart 前端开发 Android开发
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
36 1
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
2月前
|
搜索推荐 前端开发 API
探索安卓开发中的自定义视图:打造个性化用户界面
在安卓应用开发的广阔天地中,自定义视图是一块神奇的画布,让开发者能够突破标准控件的限制,绘制出独一无二的用户界面。本文将带你走进自定义视图的世界,从基础概念到实战技巧,逐步揭示如何在安卓平台上创建和运用自定义视图来提升用户体验。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开新的视野,让你的应用在众多同质化产品中脱颖而出。
77 19
|
3月前
|
IDE Java 开发工具
移动应用与系统:探索Android开发之旅
在这篇文章中,我们将深入探讨Android开发的各个方面,从基础知识到高级技术。我们将通过代码示例和案例分析,帮助读者更好地理解和掌握Android开发。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的信息和技巧。让我们一起开启Android开发的旅程吧!
|
2月前
|
JSON Java API
探索安卓开发:打造你的首个天气应用
在这篇技术指南中,我们将一起潜入安卓开发的海洋,学习如何从零开始构建一个简单的天气应用。通过这个实践项目,你将掌握安卓开发的核心概念、界面设计、网络编程以及数据解析等技能。无论你是初学者还是有一定基础的开发者,这篇文章都将为你提供一个清晰的路线图和实用的代码示例,帮助你在安卓开发的道路上迈出坚实的一步。让我们一起开始这段旅程,打造属于你自己的第一个安卓应用吧!
91 14
|
2月前
|
Java Linux 数据库
探索安卓开发:打造你的第一款应用
在数字时代的浪潮中,每个人都有机会成为创意的实现者。本文将带你走进安卓开发的奇妙世界,通过浅显易懂的语言和实际代码示例,引导你从零开始构建自己的第一款安卓应用。无论你是编程新手还是希望拓展技术的开发者,这篇文章都将为你打开一扇门,让你的创意和技术一起飞扬。

热门文章

最新文章

  • 1
    如何修复 Android 和 Windows 不支持视频编解码器的问题?
  • 2
    【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 3
    当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
  • 4
    【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
  • 5
    APP-国内主流安卓商店-应用市场-鸿蒙商店上架之必备前提·全国公安安全信息评估报告如何申请-需要安全评估报告的资料是哪些-优雅草卓伊凡全程操作
  • 6
    【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 7
    Android经典面试题之Kotlin中Lambda表达式和匿名函数的区别
  • 8
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
  • 9
    【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
  • 10
    Android学习自定义View(四)——继承控件(滑动时ListView的Item出现删除按钮)