- 浏览: 157333 次
- 性别:
- 来自: 重庆
文章分类
最新评论
-
坏猪猪:
Document doc = Jsoup.connect(ur ...
android中jsoup解析html的几个例子 -
我很温柔但是不丑:
你好。看了您的例子,实践了一下,有问题啊?没有解析出来数据?怎 ...
android中jsoup解析html的几个例子
数据集的MIME类型字符串
- 博客分类:
- android
初始MIME类型,是在学习ContentProvider的时候。
当在创建自己的ContentProvider的时,需要从抽象类ContentProvider中派生出自己的子类,并实现其中5个抽象方法:
query(Uri, String[], String, String[], String) which returns data to the caller
insert(Uri, ContentValues) which inserts new data into the content provider
update(Uri, ContentValues, String, String[]) which updates existing data in the content provider
delete(Uri, String, String[]) which deletes data from the content provider
getType(Uri) which returns the MIME type of data in the content provider
至于前四个方法,不是本文想要讨论的重点,就不做冗余的阐述了;有意思的是这个方法getType(Uri),根据帮助文档的解释,它返回一个MIME类型。
首先,先百度了一下MIME类型,根据百度百科的解释:MIME:全称Multipurpose Internet Mail Extensions,多功能Internet 邮件扩充服务。它是一种多用途网际邮件扩充协议,在1992年最早应用于电子邮件系统,但后来也应用到浏览器。MIME类型就是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。
看完百度百科的解释,相信大家和我一样,仍然不解。结合一个例子和跟老师的交流,我的理解是这样的:
在ContentProvider的getType(Uri)方法中,可以显示的返回一个MIME类型,该方法返回一个字符串,可以是任意的字符串,当我们显示的返回一个MIME类型的时候,相当于通过该方法的验证,Provider可以识别Provider中其他方法返回的Cursor的内容,不需要在进行更多的验证;如果返回其他的字符串(非android能够识别的MIME类型,例如直接返回当前的包名),则Provider在执行其他方法后,返回Cursor类型的时候,需要进行验证。
还是云里雾里的?下面来看一个使用了MIME类型的自定义ContentProvider的例子:
import android.net.Uri;
public class Shopping {
// 定义数据库的名字
public static final String DATABASE_NAME = "shopping_db";
// 定义数据库的版本
public static final int DATABASE_VERSION = 1;
// 表的名字
public static final String TABLE_NAME = "t_shopping";
// 定义数据库的字段
public static final String FIELD_ID = "_id";
public static final String FIELE_NAME = "product_name";
// 定义访问的类型
public static final int ITEM = 1;
public static final int ITEM_ID = 2;
// 定义MIME类型,访问单个记录
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.com.stone.shopping";
// 访问数据集
public static final String CONTENT_ITEM = "vnd.android.cursor.dir/vnd.stone.shopping";
// 定义访问ContentProvider权限
public static final String AUTHORITY = "com.stone.shopping";
// 定义URI
public static final Uri URI = Uri.parse("content://" + AUTHORITY + "/item");
}
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
public class MyDbHelper extends SQLiteOpenHelper {
public MyDbHelper(Context context, String name, CursorFactory factory,
int version) {
super(context, name, factory, version);
}
@Override
public void onCreate(SQLiteDatabase db) {
String sql = "CREATE TABLE " + Shopping.TABLE_NAME + " ( "
+ Shopping.FIELD_ID + " INTEGER primary key autoincrement, "
+ " " + Shopping.FIELE_NAME + " TEXT)";
db.execSQL(sql);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
String sql = "DROP TABLE IF EXISTS " + Shopping.TABLE_NAME;
db.execSQL(sql);
onCreate(db);
}
}
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.text.TextUtils;
public class MyProvider extends ContentProvider {
private MyDbHelper myDbHelper;
private static final UriMatcher mUriMatcher; // 进行匹配的Uri的设定
static {
mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
mUriMatcher.addURI(Shopping.AUTHORITY, "item", Shopping.ITEM);
mUriMatcher.addURI(Shopping.AUTHORITY, "item/#", Shopping.ITEM_ID);
}
@Override
public boolean onCreate() {
System.out.println("onCreate");
// 创建数据库
myDbHelper = new MyDbHelper(getContext(), Shopping.DATABASE_NAME, null,
Shopping.DATABASE_VERSION);
return true;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
SQLiteDatabase db = myDbHelper.getWritableDatabase();
int count = 0;
System.out.println("delete");
switch (mUriMatcher.match(uri)) {
case Shopping.ITEM:
count = db.delete(Shopping.TABLE_NAME, selection, selectionArgs);
break;
case Shopping.ITEM_ID:
// 通过Uri获取Id,根据主键进行删除
String id = uri.getPathSegments().get(1);
System.out.println(String.valueOf(uri.getPathSegments().size()));
count = db.delete(Shopping.TABLE_NAME,
Shopping.FIELD_ID + "=" + id, selectionArgs);
break;
default:
throw new IllegalArgumentException();
}
// 通知数据发生改变
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
SQLiteDatabase db = myDbHelper.getWritableDatabase();
long row = 0;
System.out.println("insert");
if (mUriMatcher.match(uri) != Shopping.ITEM) {
throw new IllegalArgumentException();
}
row = db.insert(Shopping.TABLE_NAME, Shopping.FIELD_ID, values);
if (row > 0) {
Uri noteUri = ContentUris.withAppendedId(Shopping.URI, row);
getContext().getContentResolver().notifyChange(uri, null);
return noteUri;
}
return null;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteDatabase db = myDbHelper.getReadableDatabase();
Cursor cursor = null;
System.out.println("query");
switch (mUriMatcher.match(uri)) {
case Shopping.ITEM:
cursor = db.query(Shopping.TABLE_NAME, projection, selection,
selectionArgs, null, null, sortOrder);
break;
case Shopping.ITEM_ID:
String id = uri.getPathSegments().get(1);
cursor = db.query(Shopping.TABLE_NAME, projection,
Shopping.FIELD_ID
+ "="
+ id
+ (!TextUtils.isEmpty(selection) ? " AND ("
+ selection + ')' : ""), selectionArgs,
null, null, sortOrder);
break;
default:
throw new IllegalArgumentException();
}
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
SQLiteDatabase db = myDbHelper.getWritableDatabase();
int count = 0;
System.out.println("update");
switch (mUriMatcher.match(uri)) {
case Shopping.ITEM:
count = db.update(Shopping.TABLE_NAME, values, selection,
selectionArgs);
break;
case Shopping.ITEM_ID:
String id = uri.getPathSegments().get(1);
count = db.update(Shopping.TABLE_NAME, values, Shopping.FIELD_ID
+ "="
+ id
+ (!TextUtils.isEmpty(selection) ? " AND (" + selection
+ ')' : ""), selectionArgs);
break;
default:
throw new IllegalArgumentException();
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
@Override
public String getType(Uri uri) {
// 进行Uri匹配完成不同的处理工作
switch (mUriMatcher.match(uri)) {
case Shopping.ITEM:
return Shopping.CONTENT_ITEM;
case Shopping.ITEM_ID:
return Shopping.CONTENT_ITEM_TYPE;
default:
throw new IllegalArgumentException();
}
}
}
在上面的例子中,首先有一个Shopping类,定义了一系列的常量。包括访问的数据库的相关信息和URI的定义,其中最重要的就是下面的两句,MIME类型的定义:
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.stone.shopping";
public static final String CONTENT_ITEM = "vnd.android.cursor.dir/vnd.stone.shopping";
其次是一个MyDbHelper类,继承自SQLiteOpenHelper类,用于一些数据库相关操作,这里就不赘述了。
最后的MyProvider类使我们的重头戏,首先我们来看这一段代码:
private static final UriMatcher mUriMatcher; // 进行匹配的Uri的设定
static {
mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
mUriMatcher.addURI(Shopping.AUTHORITY, "item", Shopping.ITEM);
mUriMatcher.addURI(Shopping.AUTHORITY, "item/#", Shopping.ITEM_ID);
}
UriMatcher表示一个Uri的匹配器,它会对我们请求的Uri进行匹配,而匹配的格式就是这里我们通过addURI()方法添加格式。
接下来,首先执行的就是getType(Uri)方法,下面来看该方法体中的代码:
switch (mUriMatcher.match(uri)) {
case Shopping.ITEM:
return Shopping.CONTENT_ITEM;
case Shopping.ITEM_ID:
return Shopping.CONTENT_ITEM_TYPE;
default:
throw new IllegalArgumentException();
}
当请求过来的Uri通过mUriMatcher.match(uri)方法进行匹配,根据不同的匹配值(Shopping.CONTENT_ITEM 或者 Shopping.CONTENT_ITEM_TYPE)来返回不同的MIME类型。
下面我们来结合query(Uri, String[], String, String[], String) 这个方法来解释一下:
在这个方法中,返回的是一个Cursor游标对象。而Cursor中是单条的记录还是一个集合,需要和在getType()方法中返回的类型保持一致。当返回的MIME类型是Shopping.CONTENT_ITEM时,Cursor应该是一个集合;当返回的MIME类型是Shopping.CONTENT_ITEM_TYPE时,Cursor应该是单条记录。
由于在getType()方法里面,我们显示的返回了android平台可以识别的MIME类型,所以在执行query方法返回Cursor对象的时候,系统将不需要再进行验证,从而可以说是节省了系统开销。
话已至此,那么何谓android平台可以识别的MIME类型呢?下面来分析一下MIME类型的结构:
其实,MIME类型其实就是一个字符串,中间有一个 “/” 来隔开,“/”前面的部分是系统识别的部分,就相当于我们定义一个变量时的变量数据类型,通过这个“数据类型”,系统能够知道我们所要表示的是个什么东西。至于 “/” 后面的部分就是我们自已来随便定义的“变量名”了。
那么,既然MIME类型就是一个字符串,那么我们的getType( )自然也可以随便返回一个系统不能识别的字符串啦?没错,有些时候我们确实也这样处理,比如说可以这样写:
public String getType(Uri uri) {
return getContext().getPackageName();
}
这里,我们把当前上下文的包名返回了。这样处理的结果是怎样的呢?
简单的说,系统不能够识别它了,也就不会做任何处理。仍然以query方法来说,当执行完方法体(这里需要注意一下:在这种情况下,即使我们没有通过返回MIME类型字符串来进行验证处理,但是在query方法中再次对Uri进行了匹配并根据不同的Uri类型进行了不同的操作)返回Cursor对象的时候,这时候系统不能肯定返回的Cursor对象是否合法,因此需要对其进行验证,这样对系统资源算是一个浪费了吧。所以,我们最好还是显示的返回一个MIME类型吧,当然要写正确了,让我们android平台可以识别。
发表评论
-
Android中dip(dp)与px之间单位转换
2012-04-30 14:35 1465Android中dip(dp)与px之间单位转换 dp这个单 ... -
java字符串处理(分割截取替换等)
2012-01-06 17:04 20481/** * 分割字符串 * * @pa ... -
android database leak found
2012-01-06 09:52 1709package com.archermind; imp ... -
android中context
2012-01-04 19:48 2243我找了很多资料,还是不能弄懂,记下来,以后慢慢理解。 Con ... -
android中易错点
2012-01-03 10:58 13091.字符串匹配: equals和==是有区别的 用jsou ... -
android中jsoup解析html的几个例子
2012-01-03 10:58 392431.获取百度所有链接的例子(通过ID): public cl ... -
【Android】Uri、UriMatcher、ContentUris详解
2011-12-15 10:26 51361.Uri 通用资源标志 ... -
ContentProvider和ContentResolver还有SQLiteDatabase的关系
2011-12-14 22:51 1319在Android系统中,存储数据的方式一共有5种:1.Shar ...
相关推荐
1.3 测试一个对象是否是类字符串 8 1.4 字符串对齐 10 1.5 去除字符串两端的空格 11 1.6 合并字符串 11 1.7 将字符串逐字符或逐词反转 14 1.8 检查字符串中是否包含某字符集合中的字符 15 1.9 简化字符串的...
ContentType:指定MIME媒体数据类型,描述正文中包含的数据,使用户代理决定如何显示数据,常用的有text/html,text/xml。 TIdSMTP组件简介 TIdSMTP是TIdMessageClient派生出的一个简单邮件传输协议和SMTP客户端...
这里面实现了很多的帮助方法,比如正则验证,加密,解密,MD5加密,字符串的处理等操作。 2.最新的 PageValidate 类 主要是实现了验证,是否为空,是否为数字等。 3.JavascriptHelp 帮助输出简单的JS代码 4.最新...
6.从字符串里随机得到,规定个数的字符串. 复制代码 22.条形码 BarCodeToHTML 本类是个条码生成类,大家可根据需要自己设置,非常好用 23.图片 ImageClass 主要功能有:缩略图片,图片水印,文字水印,调整光暗...
• 2.11.htm 字符串型转换为逻辑型数据 • 2.12.htm toLowerCase()方法 • 2.13.htm 通过字符串调用toLowerCase()方法 • 2.14.htm 使用值的数据操作 • 2.15.htm 对数据的...
RFC2046多用途Internet邮件扩展(多用途网际邮件扩充协议(MIME))第二部分:媒体类型 RFC2047多用途网际邮件扩充协议(MIME)(多用途Internet邮件扩展)第三部分:信息标题扩展用于非ASCII文本 RFC2048多用途Internet邮件...
3.5.5 文本字符串 3.5.6 使用uri 3.5.7 使用颜色 3.5.8 使用长度 3.5.9 内容类型(mime类型) 3.5.10 语言代码 3.5.11 字符编码 3.5.12 单字符 3.5.13 日期和时间 3.5.14 链接类型 3.5.15 介质描述符 3.5.16 脚本数据 ...
• 2.11.htm 字符串型转换为逻辑型数据 • 2.12.htm toLowerCase()方法 • 2.13.htm 通过字符串调用toLowerCase()方法 • 2.14.htm 使用值的数据操作 • 2.15.htm 对数据的...
RFC1558_LDAP研究过滤器的字符串表达 RFC1571_Telnet环境选项互用性问题 RFC1590_媒体类型注册过程 RFC1591_域名系统的结构和授权 RFC1597_私有Internet的地址分配 RFC1605_SONET to Sonnet翻译 RFC1606_用IP版本9的...
RFC1558 LDAP研究过滤器的字符串表达 RFC1571 Telnet环境选项互用性问题 RFC1590 媒体类型注册过程 RFC1591 域名系统的结构和授权 RFC1597 私有Internet的地址分配 RFC1605 SONET to Sonnet翻译 RFC1606 用IP版本9的...
RFC1558 LDAP研究过滤器的字符串表达 RFC1571 Telnet环境选项互用性问题 RFC1590 媒体类型注册过程 RFC1591 域名系统的结构和授权 RFC1597 私有Internet的地址分配 RFC1605 SONET to Sonnet翻译 RFC1606 用IP版本9的...
2.3.1. 保存 ACL 数据确保持久性 2.3.2. 使用声明(Assert)来编写条件性的 ACL 规则 3. Zend_Auth 3.1. 简介 3.1.1. 适配器 3.1.2. 结果 3.1.3. 身份的持久(Persistence) 3.1.3.1. 在PHP Session 中的缺省...
.NET 2.0中的字符串比较 小试ASP.NET 2.0的兼容性 为 asp.net 2.0 的菜单控件增加 target 属性 ASP.NET 2.0 的内部变化 常见的 ASP.NET 2.0 转换问题和解决方案 Asp.Net2.0无刷新客户端回调 体验.net 2.0 的优雅(1...