您的位置:首页 > 编程语言 > PHP开发

ContentProvider的使用

2016-06-12 19:08 369 查看
ContentProvider的使用
ContentProvider是Android的四大组件之一,他可以把自己的数据暴漏出来,让其他应用可以对该数据进行增删改查,若应用程序通过内容提供者暴漏了自己的数据,则无论该应用程序是否启动了,其他应用程序都可通过该接口来操作数据。内容提供者操作的数据可以是数据库数据也可以是文件等他存储方式,如要操作xml文件中user节点下的name节点,通过ContentResolver操作内容提供者,Uri是提供者和操作者之间进行数据交换的标识,通过系统找到对应的ContentProvider,ContentResolver的操作实际是Uri对应的ContentProvider实现的对数据的操作,执行的提供者中的增删改查,ContentResolver执行的insert(),delete(),update(),query()实际是ContentProvider执行的对应的方法,最终执行的都是在内容提供者中。
内容提供者在应用中多以单例模式使用
ContentProvider的使用:
1.内容提供者
(1)   定义类继承ContentProvider基类,重写方法
(2)  在清单文件中注册,注册时需要指定authorities,该属性用于其他应用找到该内容提供者的标记,从而进行操作数据,并设置为可供外部应用调用(exported)
内容提供者的方法:
创建时调用的方法:Oncreate():该方法在内容提供者创建后会被调用,当其他应用第一次访问内容提供者时调用
插入数据时调用的方法 :PublicUri insert(Uri uri,ContentValues values);第一个参数是插入数据的uri地址标记,第二个参数是插入的数据
删除数据时调用的方法:publicint delete(Uri uri,String selection, String[] selectionArgs);//第一个参数是操作的地址,第二个参数是删除的数据的where条件,第三个参数是第二个参数中的条件中的值
更新时调用的方法:public intupdata(Uri uri,ContentValues values,String selection,String[] selectionArgs);//第一个参数是操作的数据的位置,第二参数是根据条件找到的数据修改后的结果,第三个参数是更新数据的条件,第三个参数是更新条件中的?对应的值
查询时调用的方法:publicCursor query(Uri uri,String[] projection,String selection,String[]selectionArgs,String sortOrder);//第一个参数是查询数据的地址,第二个参数是筛选返回的结果,第三个参数是查询的条件不需要则为null,第四个参数是查询条件中的?所指代的数值,第五个参数是查询出的数据的排列方式,是升序或降序。
PublicString getType(Uri uri):该方法用于放回当前Uri所代表的MIME类型,若该Uri对应的数据可能包含多条记录,则MIME类型字符串应该以vnd.android.cursor.dir/开头,若只有一天记录则以vnd.android.cursor.item/开头
2.内容操作者
ContentResolver是用于操作内容提供者提供的数据,在其他应用中通过ContentResolver修改提供的数据。每个方法的返回值的类型就是内容提供者中对应的方法的返回值,执行的也是对应的提供者中的方法。
Context的getContentReslover(),获取ContentReslover对象。
Insert(Uri,ContentValues);//向对应的内容提供者中插入ContentValues的数据。
delete(Uri,String where,String[] selectionArgs);//删除uri对应的内容提供者中的数据,查找条件是where,where中的参数的值是selectionArgs
update(Uri,ContentValues,String where,String[] selectionArgs);//修改uri对应的内容提供者中根据条件找到的数据成ContentValues数据
quert(Uri,String[] projection,String selection,String[]selectionArgs,String sortOrder);查询内容提供者中查询出的数据返回cursor
3.Uri介绍
Uri相当于网络的网址,用于指定操作的位置,Uri分为3部分
以content://org.crazyit.providers.dictproviders/words为例
content://:这是固定的开头,相当于URl中的http://
org.crazyit.providers.dictproviders:这个部分是内容提供者注册中的authorities,通过该部分找到操作的内容提供者,相当于URl中的域名部分
words://:数据部分,相当于URl中的具体文件部分
4.UriMatcher介绍
UriMatcher是用于对uri进行匹配,多使用于在内容提供者中进行增删改查操作时对uri进行匹配,通过匹配进行区分操作,
方法:
addURI(authority,path, code)//第一个参数对内容提供者而言是内容提供者中注册时的authorities属性规定的内容提供者的标记,第二个参数是操作的表名,第三个参数是匹配码,当进行匹配是方法返回的值
match(Uri);进行匹配时调用的方法
5. ContentUri
    Uri的工具类,多用于对uri和数据id的添加和解析操作,例如内容提供者中数据操作成功后,返回的uri是插入数据后的添加id后的uri可通过下面的方法进行操作: withAppendedld(uri,id);//将一个id添加到一个uri的末尾形成一个新的uri
parseId(uri);//用于指出一个uri中所包含的id
使用例子:
实体类:
public
class
Words {
    public
final static
String authority="com.myContentProvider";
    public
static final
class
Word{
        public
final static
  String id="id";
        public
final static
  String word="word";
        public
final static
  String detail="detail";
        public
final static
  Uri urione=Uri.parse("content://com.myContentProvider/words");
        public
final static
  Uri uritwo=Uri.parse("content://com.myContentProvider/word");
    }
}
其中一个应用中定义的内容提供者
public
class
MyContentProvider extends ContentProvider{
private
static
UriMatcher matcher=new UriMatcher(UriMatcher.NO_MATCH);//uri匹配器,添加多个Uri则可以匹配多个,其中有匹配码可以用于匹配后返回的值
private
staticfinalint
WORES=1;
private
staticfinalint
WORD=2;
private
staticfinalint
WORDD=4;
private
staticfinalint
WORDDS=5;
private Heplpter
heplpter;
    //当第一次调用内容提供者时调用,只调用一次
    @Override
    public
boolean
onCreate() {
        heplpter=new Heplpter(this.getContext(),
"EnglishDB.db",null,1);//拿到数据库对象就可以对数据库增删改查了
        matcher.addURI(Words.authority,
"English",WORES);//用于操作English表,对数据库而言第二个参数是表名,第一个参数是本内容提供者的zuthorities属性,第三个数据是uri的匹配码,当执行增删改查操作的时候,就是通过matcher匹配uri返回的值:相当于content://authorities/表名/id
        matcher.addURI(Words.authority,
"English/#",WORD);//用于操作English表的多条数据的匹配//English/#代表的是English表下的某一条数据,使用于列表点击某条查询某条的数据,
        matcher.addURI(Words.authority,
"Englishdd",WORDD);//用于操作Englishdd表的多条数据的匹配
        matcher.addURI(Words.authority,
"Englishdd/#",WORDD);//用于操作Englishdd表的单条数据的匹配
        return
true
;
    }
    //返回uri所代表的数据的mime类型,若uri对应的数据可能包含多条记录,则mime类型字符串应该以vnd.android.cursor.dir/开头,若只包含一条记录,则对应的应该是vnd.android.cursor.item/开头
    @Override
    public String getType(Uri uri){
        //若操作的是集合类型则返回WORDS,若只有一条数据则返回WORD下的数据
        switch(matcher.match(uri)){
        case
WORES:
            return
"vnd.android.cursor.dir./English";//dir是目录的意思,意思是返回English表的集合,这个的返回是根据我们操作的数据返回的结果是一条数据还是一个集合
        case
WORD:
            return
"vnd.android.cursor.item./English";//item是项的意思,意思是返回English表的某一线,这个的返回是根据我们操作的数据返回的结果是一条数据还是一个集合
        case
WORDD:
            return
"vnd.android.cursor.dir./Englishdd";//dir是目录的意思,意思是返回Englishdd表的集合,这个的返回是根据我们操作的数据返回的结果是一条数据还是一个集合
        case
WORDDS:
            return
"vnd.android.cursor.item./Englishdd";//item是项的意思,意思是返回Englishdd表的某一线,这个的返回是根据我们操作的数据返回的结果是一条数据还是一个集合
            default:
                throw
new
IllegalArgumentException("未知Uri:"+uri);
        }
    }
    //根据uri删除selection条件匹配的所有记录
    @Override
    public
int
delete(Uri uri, Stringselection, String[] selectionArgs) {
        SQLiteDatabasedb=heplpter.getWritableDatabase();
        int num=0;
        //uri可能有多个,//下面这个就是对uri进行分类,
        switch(matcher.match(uri)){
        case
WORES:
            num=db.delete("English",selection, selectionArgs);
            break;
        case
WORD:
            long id=ContentUris.parseId(uri);
            StringwhereClause=Words.Word.id+"="+id;//id=2的数据
            if(selection!=null&&!"".equals(selection)){
                whereClause=whereClause+"and"+selection;//拼接条件
            }
            num=db.delete("English",whereClause, selectionArgs);
            break;
        default:
                throw
new
IllegalArgumentException("未知Uri:"+uri);

        }
        getContext().getContentResolver().notifyChange(uri,null);
        db.close();
        return num;
    }
    //根据uri插入对应values数据
    @Override
    public Uri insert(Uri uri,ContentValues values) {
        SQLiteDatabasedb=heplpter.getWritableDatabase();
        switch(matcher.match(uri)){
        case
WORES:
            long rowId=db.insert("English",Words.Word.id,values);//返回值是插入数据的行id
            if(rowId>0){
                UriwordUri=ContentUris.withAppendedId(uri, rowId);
                getContext().getContentResolver().notifyChange(wordUri,null);
                db.close();
                return wordUri;//插入成功后返回的是插入数据的uri
            }
            break;
            default:
                db.close();
                throw
new
IllegalArgumentException("未知Uri:"+uri);
        }
       
        return
null
;
    }
    //根据uri查询出selection条件所匹配的所有记录,,projection是一个列表名,表明只选择出指定的数据列。
    @Override
    public Cursor query(Uri uri,String[] projection, String selection, String[] sectionArgs,
            StringsortOrder) {
        SQLiteDatabasedb=heplpter.getWritableDatabase();
        Cursorcursor=null;
        switch(matcher.match(uri)){
        case
WORES:
            cursor=db.query("English",projection, selection, sectionArgs,
null, null, sortOrder);
//          db.close();
            return cursor;
        case
WORD:
            long id=ContentUris.parseId(uri);
            StringwhereClause=Words.Word.id+"="+id;
            if(selection!=null&&!"".equals(selection)){
                whereClause=whereClause+"and"+selection;
            }
            cursor=db.query("English",projection, selection, sectionArgs,
null, null, sortOrder);
//          db.close();//不能关闭数据库
            return cursor;
            default:
                throw
new
IllegalArgumentException("未知Uri:"+uri);
        }
    }
    //根据uri修改selection条件匹配的记录
    @Override
    public
int
update(Uri uri,ContentValues values, String selection, String[] selectionArgds) {
        SQLiteDatabasedb=heplpter.getWritableDatabase();
        int num=0;
        switch(matcher.match(uri)){
        case
WORES:
            num=db.update("English",values, selection, selectionArgds);
            break;
        case
WORD:
            long id=ContentUris.parseId(uri);
            StringwhereClause=Words.Word.id+"="+id;
            if(selection!=null&&!"".equals(selection)){
                whereClause=whereClause+"and"+selection;
            }
            num=db.update("English",values, whereClause, selectionArgds);
            break;
            default:
                throw
new
IllegalArgumentException("未知Uri:"+uri);
        }
        getContext().getContentResolver().notifyChange(uri,null);
        db.close();
        return num;
    }
}
SQLiteOpenHelpter:
 
public class Heplpter extends SQLiteOpenHelper{
 
   
    //name是创建的数据库的名称后缀是.db,factory是Cursor工厂可以写null为默认的工厂,vertsion是数据库的版本
    publicHeplpter(Context context, String name, CursorFactory factory,
            intversion) {
        super(context,name, factory, version);//使用默认的cursorFactory
    }
    //当调用getWritableDatabase()(以写的方式打开数据库,若数据库的磁盘空间慢了,数据库则只能读不能写了,此时用本方法打开则会报错)或getReadablDatabase()(先以读写的方式打开数据库,若数据库的磁盘空间慢了,此时打开数据库就会打开失败,则会以只读的方式打开数据库)方法获取数据库对象时调用,若不存在数据库则系统或自动创建爱一个在调用oncreate(),其中自动创建一个表,用于操作数据
    @Override
    publicvoid onCreate(SQLiteDatabase db) {
        db.execSQL("createtable English(id integer primary key autoincrement,word varchar(255),detailvarchar(255))");//执行sql语句
    }
 
    //当版本变化时调用,当创建本实例对象时会传入一个version,该version高于之前的版本号则会调用.
    @Override
    publicvoid onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
       
    }
//  publicHeplpter getInstance(){
//      returnnew
//  }
 
}
//清单注册:
<provider
 android:name="com.example.sharecontent.mycontentprovider.MyContentProvider"
android:authorities="com.myContentProvider"
android:exported="true"
></provider>
//另一个应用的使用ContentResolver
另一个应用布局
<?xml
version="1.0"encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
>
 
   <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:orientation="vertical"
>
 
        <Button
           android:id="@+id/insert"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="插入数据"
/>
 
        <Button
           android:id="@+id/delete"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="删除数据"
/>
 
        <Button
           android:id="@+id/update"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="修改数据"
/>
 
        <Button
           android:id="@+id/query"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="查询数据"
/>
 
        <EditText
           android:id="@+id/change"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:hint="修改数据或查询数据的字段"
/>
 
        <EditText
           android:id="@+id/content"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:hint="文字描述"
/>
 
        <EditText
           android:id="@+id/willChange"
           android:layout_width="match_parent"
           android:layout_height="40dp"
           android:hint="请输入将被修改的词"
/>
   </LinearLayout>
 
   <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="3"
        android:orientation="vertical"
>
 
        <ListView
           android:id="@+id/showWords"
           android:layout_width="match_parent"
           android:layout_height="wrap_content">
        </ListView>
   </LinearLayout>
 
</LinearLayout>
另一个应用的类
public
class
ShowMessage extends Activity{
    EditTextchange;
    EditTextcontent;
    ListViewshowWords;
    ArrayAdapteradapter;
    List<String>listWords;
    EditTextwillChange;
    @Override
    protected
void
onCreate(BundlesavedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_showmessage);
       
        willChange=(EditText)findViewById(R.id.willChange);
        Buttoninsert=(Button) findViewById(R.id.insert);
        Buttondelete=(Button) findViewById(R.id.delete);
        Buttonupdate=(Button) findViewById(R.id.update);
        Buttonquery=(Button) findViewById(R.id.query);
        change=(EditText)findViewById(R.id.change);
        content=(EditText)findViewById(R.id.content);
        showWords=(ListView)findViewById(R.id.showWords);
        final ContentResolverresolver=getContentResolver();
        final Uri uri=Uri.parse("content://com.myContentProvider/English");//通過uri找到內容提供者
        insert.setOnClickListener(new View.OnClickListener(){
           
            @Override
            public
void
onClick(View arg0) {
                Stringword=change.getText().toString();
                Stringcontents=content.getText().toString();
                ContentValuesvalues=newContentValues();
                values.put("word", word);
                values.put("detail",contents);
                Uriuris=resolver.insert(uri, values);
                Toast.makeText(ShowMessage.this,
"添加成功后的uri是"+uris, Toast.LENGTH_SHORT).show();
            }
        });
        delete.setOnClickListener(new View.OnClickListener(){
           
            @Override
            public
void
onClick(View arg0) {
                Stringword=change.getText().toString();
//              intid=resolver.delete(uri, "", null);//删除uri指定的数据
                int id=resolver.delete(uri,"word=?",newString[]{word});
                Toast.makeText(ShowMessage.this,
"删除的是数据"+id, Toast.LENGTH_SHORT).show();
            }
        });
        update.setOnClickListener(new View.OnClickListener(){
           
            @Override
            public
void
onClick(View arg0) {
                Stringword=change.getText().toString();
                Stringcontents=content.getText().toString();
                Stringwill=willChange.getText().toString();
                ContentValues values=new ContentValues();
                values.put("word", word);
                values.put("detail",contents);
                int id=resolver.update(uri,values,
"word=?",newString[]{will});//更新内容提供者中的word字段是will的数据
//              intid=resolver.update(uri, values, "", null);//更新内容提供者中的uri字段指定的行
                Toast.makeText(ShowMessage.this,
"更新的数据条数"+id, Toast.LENGTH_SHORT).show();
            }
        });
        query.setOnClickListener(new View.OnClickListener(){
           
            @Override
            public
void
onClick(View arg0) {
                Cursorcursor=resolver.query(uri, null,
null,null,null);
                listWords.clear();
                while(cursor.moveToNext()){
                    listWords.add(cursor.getString(1)+":"+cursor.getString(2));
                }
                adapter.notifyDataSetChanged();
                cursor.close();
            }
        });
        listWords=newArrayList<String>();
        adapter=newArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1,
listWords);
        showWords.setAdapter(adapter);
    }
}
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息