小弟也是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可以识别自身其他方法返回的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() {

// 创建数据库
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;

switch (mUriMatcher.match(uri)) {

case Shopping.ITEM:

ount = 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;

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;

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;

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)方法进行匹配,根据不同的匹配值来返回不同的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平台可以识别。


转:http://blog.csdn.net/h3g2010/article/details/6093366


更多相关文章

  1. 单选按钮(RadioButton)和复选框(CheckBox)的介绍与应用
  2. Android中BaseAdapter原理
  3. Android最好用的播放器ExoPlayer的使用及自定义UI
  4. Android(安卓)JNI Java参数类型与本地参数类型对照
  5. android 通过数组,流播放声音的方法
  6. [置顶] Android高手进阶教程(四)之----Android(安卓)中自定义属
  7. 史上最全selector和shape使用方法 Android(安卓)ListView 列表项
  8. 搭建IPC通信框架(RPC)
  9. 修改系统action bar字体大小、粗细、颜色等样式的方法

随机推荐

  1. android 开机优化(类和资源预加载优化)
  2. 下一版本的Android OS ——Jelly Bean
  3. Android(安卓)如何访问Assets文件夹里面
  4. Android在一个Activity中更新另一个Activ
  5. Android ActionBar的基本用法
  6. Android Memory Management
  7. Android Fragment 非常详细的一篇
  8. android:添加usb键盘+按键布局和映射的修
  9. android的helloworld工程目录学习
  10. Android第一行代码学习笔记六----手机多