`

content provider 的简单介绍(sdk doc翻译)

阅读更多
内容提供器
   内容提供器是用来读取和存储数据,使用它可以将我们自己的数据共享给别人,同时可以读取到别人的数据在别人容许的情况下。他是唯一个可以在不同的应用程序间共享数据的方式,没有公共的存储区域,所有的android应用程序都可以访问。

    android系统自带一些内容提供器为常用的数据类型,如音乐,视频,图片,联系人资料等,你可以通过android.provider包查看这些东东,你可以通过这些内容提供器查询他们包含的数据(但是你必须要得到其他用户程序的许可)。
   
     如果你想让你的数据可以让别人共享,你必须做两个操作,1.你需要建立你自己的contentProvider(一个系统提供的contentProvider的子类)存储数据,2.你通过别人提供的provider去存储自己的数据(这个provider必须很你需要操作的数据类型一样,且你拥有这个provider写的权利)。

   contentprovider基础
   
    一个contentprovider怎样存储数据,完全有他的开发者控制,但是所有的contentprovider必须实现相同的接口,用来查询内容和返回结果,比如添加数据,修改,和删除。
   
   用户可以通过系统提供的一个接口getContentResolver回去contentResolver对象(在activity中调用这个对象),当你得到这个对象后,
  一般在activity中使用的方法为
  ContentResolver c = getContentResolver();这个时候你就可以和提供contentprovider的应用进行交互了,
  当我们发起一个查询事件时,系统识别contentProvider通过在查询中提供的uri,然后确定这个contentprovider启动并且在运行,android系统在启动的时候就初始化所有的contentprovider对象(自己提供的contentprovider需要在manifest文件中声明,具体做法一会讲)
对一些公共的应用你永远不需要自己去实现(开源软件的好处,省力,省钱,支持开源,但同时也降低了我们程序员的水准),实际上你根本不需要直接和一个contentprovider打交道(除非是自己的),android系统为没个contentprovider提供了一个实例(单例模式),但是它可以和多个contentresolver打交道(线程安全的),线程安全是由contentresolver和contentprovider完成的,我们使用者不比为此担忧。

  数据模式

    contentprovider是按照表的方式公开自己的数据。每一个行是一条记录,每一列是一个具体的值,这里就不举例了,如果连表都不知道的话,建议你还是别存从事软件开发了,免得降低程序员的水准,呵呵,题外话

    在android的中,每一行数据都必须包含一列,列名为"_id",他是表的主键。主键的概念和作用参考数据库方面的书

    每一个查询都返回一个Cursor对象,做过oracle pl/sql编程的可定知道他的意思。cursor对象可以让我们从一行移另一行,一列移动到另一列,可以很方便的读数据。他还提供读取特定类型的数据的方法,如getString,getInteger等方法,前提是你必须知道每个字段所代表的类型。(一会将详细介绍查询结果和cursor对象)

    Uri
    uri的作用是准确的定位我们需要的contentprovider提供的数据,否则就会乱套(不安全的,得带),每一个contentprovider都提供一个公开的uri ,他可以准确的标识一个数据集,一个contentprovider控制多个数据集,通过uri可以准确的标识他们,中的每一个数据集。所有的uri必须以content://开头,content:是作为识别contentprovider的标识。

   如果你自己定义了一个contentprovider,那么你也需要为他建立一个uri,简化他人调用的工作and make future updates cleaner(请大侠解释),android定义content_uri 常量给所有的和平台交互的provider(Android defines CONTENT_URI constants for all the providers that come with the platform)。例如,查询联系的联系人和联系的图片的uri为:
  android.provider.Contacts.Phones.COntent_URI 和android.provider.Contacts.Photos.CONTENT_URI.
uri 对所有和contentprovider交互的用户。每个contentresolver的方法的第一个参数就是uri,他定义了将要和哪个contentprovider的contentresolver进行对话,以及将要对哪个表进行操作。

   查询一个contentprovider
   
    你需要分三步去查询一个contentprovidr

     1.contentprovidr定义的uri
     2.你需要返回的表的列名
     3.这些数据的类型(本人有点疑问)

     如果你要查询某条特定的数据,你还需要制定ID

   生成查询
   
     你可以通过ContentResolver对象的query方法或者Activity.managedQuery方法,这个方法的参数都一样,都返回一个cursor对象,但是managedQuery方法可以让activity管理cursor对象的生命周期,他可以做好多事情,比如,当activity pauses以后,会自动关闭cursor对象。当activity restart的时候,它可以自动去重新查询。你也可以调用activit的startmanagingCursor(Cursor c)方法去管理这个对象。

query方法和managedQuery方法的第一个参数为provider的uri,关于uri上面已经介绍过了,

    android系统提供了一些辅助方法,比如,COntentUris.withAppendedId()和Uri.withAppendedPath()方法,他们可以很方便的为uri添加一个id,两个方法都是静态的,都返回一个uri对象,下面是android 帮助文档中提供的例子

     import android.provider.Contacts.People;
     import android.content.ContentUris;
     import android.net.Uri;
    import android.database.Cursor;

// Use the ContentUris method to produce the base URI for the contact with _ID == 23.
  //Uri myPerson = ContentUris.withAppendedId(People.CONTENT_URI, 23);

// Alternatively, use the Uri method to produce the base URI.
  // It takes a string rather than an integer.
  Uri myPerson = Uri.withAppendedPath(People.CONTENT_URI, "23");

// Then query for this specific record:
Cursor cur = managedQuery(myPerson, null, null, null, null);

query()和managedQuery()方法的参数代表的意思如下:

        参数1:uri。参数2:需要返回的列名,比如_id,number,nember_key等,如果为空,则返回所有列。参数3:相当于sql语句的where条件,比如 “_id” = 12,"_id" = ? 。如果为null的时候,则返回所有列,前提是你的uri是返回全部的uri。参数4:如果参选3中包含形如"_id" = ?的条件,那么此项不能为空。否则此项为空,目的是提供查询速度,让sql语句软解析。参数5:是排序,比如要按照id排序,则为“id desc ”,不需要加order by。详细请查看android api android.content.contentResolver
    
   查询返回的数据
  
    每个查询都会返回o个或者多条记录。不会返回null,而且每行都会包含_id这列,
 
   读取返回的数据

   从cursor中读数据的时候,一定要知道数据的类型,但是你也可以通过getString方法,读取到所有数据,但是返回的对象都是string类型的,在你实际应用中,你还是要转换成真正的类型,所以还是第一次就使用对象的get方法把,你可以使用index或者列名去读数据。好像没有提供直接使用列名读数据的方法,不知道为什么,待解(难道是我没注意到)。
如下:
if (cur.moveToFirst()) {

        String name;
        String phoneNumber;
        int nameColumn = cur.getColumnIndex(People.NAME);
        int phoneColumn = cur.getColumnIndex(People.NUMBER);
        String imagePath;
   
        do {
            // Get the field values
            name = cur.getString(nameColumn);
            phoneNumber = cur.getString(phoneColumn);
          
            // Do something with the values.
            ...

        } while (cur.moveToNext());

    }

如果一个查询返回的是二进制数据,如image或者音乐。那么数据可以直接存在表中,也可以通过一个uri链接到相应内容。使用uri可以获取数据。一般情况下,小数据,如20-50k或者更小的,直接存在数据库,可以通过getBlod()方法到到btye数据。如果table存在的uri,那么你不需要直接打开或者读取这个文件,(不过要有这个权限)。你应该调用ContentResolver.onpenInputStream()获取inputStream对象,然后可以读。

  修改数据

    1.add
    2.updata
    3.batch update
    3.delete
  
   一. 添加数据
       添加数据的第一步,你需要创建一个key-value对象在ContentValues(相当于map,内部实现还是以map实现的,android封装了java的map对象)。数据设置好后,调用contentResolver的insert方法就可以插入了
     insert方法返回的不是我们想象的id类型,而是一个uri对象,代表新插入记录的uri。你可以使用他查询刚才添加的记录。如下:
ContentValues values = new ContentValues();

// Add Abraham Lincoln to contacts and make him a favorite.
values.put(People.NAME, "Abraham Lincoln");
// 1 = the new contact is added to favorites
// 0 = the new contact is not added to favorites
values.put(People.STARRED, 1);

Uri uri = getContentResolver().insert(People.CONTENT_URI, values);


  二. 修改,删除就不说了,基本上差不多,update和delete方法。

  创建一个contentprovider
  
 
  1.创建一个contentProvider子类
  2.定义uri
  3.使用创建的类。打开一个SQLiteDatabase对象。openRendHelper和openWirterHelper方法。
  4.在manifest文件中声明这个类,一定要声明,<provider android:name="com.example.autos.AutoInfoProvider"
          android:authorities="com.example.autos.autoinfoprovider"
          . . . />
</provider>

  实现类里,需要实现的方法有 query,insert update getType oncreate
  格式为 content://xxx.xxx.xxx全部数据,某一条数据 content://xxx.xxx.xxx/id
<provider android:name="com.example.autos.AutoInfoProvider"
          android:authorities="com.example.autos.autoinfoprovider"
          . . . />
</provider>
import java.util.Calendar;
import java.util.Date;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class DiaryDbAdapter {

public static final String KEY_TITLE = "title";
public static final String KEY_BODY = "body";
public static final String KEY_ROWID = "_id";
public static final String KEY_CREATED = "created";

private static final String TAG = "DiaryDbAdapter";
private DatabaseHelper mDbHelper;
private SQLiteDatabase mDb;

private static final String DATABASE_CREATE = "create table diary (_id integer primary key autoincrement, "
+ "title text not null, body text not null, created text not null);";

private static final String DATABASE_NAME = "database";
private static final String DATABASE_TABLE = "diary";
private static final int DATABASE_VERSION = 1;

private final Context mCtx;

private static class DatabaseHelper extends SQLiteOpenHelper {

DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(DATABASE_CREATE);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS diary");
onCreate(db);
}
}

public DiaryDbAdapter(Context ctx) {
this.mCtx = ctx;
}

public DiaryDbAdapter open() throws SQLException {
mDbHelper = new DatabaseHelper(mCtx);
mDb = mDbHelper.getWritableDatabase();
return this;
}

public void closeclose() {
mDbHelper.close();
}

public long createDiary(String title, String body) {
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_TITLE, title);
initialValues.put(KEY_BODY, body);
Calendar calendar = Calendar.getInstance();
String created = calendar.get(Calendar.YEAR) + "年"
+ calendar.get(Calendar.MONTH) + "月"
+ calendar.get(Calendar.DAY_OF_MONTH) + "日"
+ calendar.get(Calendar.HOUR_OF_DAY) + "时"
+ calendar.get(Calendar.MINUTE) + "分";
initialValues.put(KEY_CREATED, created);
return mDb.insert(DATABASE_TABLE, null, initialValues);
}

public boolean deleteDiary(long rowId) {

return mDb.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
}

public Cursor getAllNotes() {

return mDb.query(DATABASE_TABLE, new String[] { KEY_ROWID, KEY_TITLE,
KEY_BODY, KEY_CREATED }, null, null, null, null, null);
}

public Cursor getDiary(long rowId) throws SQLException {

Cursor mCursor =

mDb.query(true, DATABASE_TABLE, new String[] { KEY_ROWID, KEY_TITLE,
KEY_BODY, KEY_CREATED }, KEY_ROWID + "=" + rowId, null, null,
null, null, null);
if (mCursor != null) {
mCursor.moveToFirst();
}
return mCursor;

}

public boolean updateDiary(long rowId, String title, String body) {
ContentValues args = new ContentValues();
args.put(KEY_TITLE, title);
args.put(KEY_BODY, body);
Calendar calendar = Calendar.getInstance();
String created = calendar.get(Calendar.YEAR) + "年"
+ calendar.get(Calendar.MONTH) + "月"
+ calendar.get(Calendar.DAY_OF_MONTH) + "日"
+ calendar.get(Calendar.HOUR_OF_DAY) + "时"
+ calendar.get(Calendar.MINUTE) + "分";
args.put(KEY_CREATED, created);

return mDb.update(DATABASE_TABLE, args, KEY_ROWID + "=" + rowId, null) > 0;
}
}
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics