ContentProvider的使用

本文详细介绍了Android中的ContentProvider组件,包括其工作原理、如何定义及注册ContentProvider,以及如何使用ContentResolver进行数据操作。同时提供了完整的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ContentProvider的使用

ContentProvider是Android的四大组件之一,他可以把自己的数据暴漏出来,让其他应用可以对该数据进行增删改查,若应用程序通过内容提供者暴漏了自己的数据,则无论该应用程序是否启动了,其他应用程序都可通过该接口来操作数据。内容提供者操作的数据可以是数据库数据也可以是文件等他存储方式,如要操作xml文件中user节点下的name节点,通过ContentResolver操作内容提供者,Uri是提供者和操作者之间进行数据交换的标识,通过系统找到对应的ContentProviderContentResolver的操作实际是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 classWords {

    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 classMyContentProvider extends ContentProvider{

private staticUriMatcher matcher=new UriMatcher(UriMatcher.NO_MATCH);//uri匹配器,添加多个Uri则可以匹配多个,其中有匹配码可以用于匹配后返回的值

private staticfinalintWORES=1;

private staticfinalintWORD=2;

private staticfinalintWORDD=4;

private staticfinalintWORDDS=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 newIllegalArgumentException("未知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 newIllegalArgumentException("未知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 newIllegalArgumentException("未知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 newIllegalArgumentException("未知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 newIllegalArgumentException("未知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 classShowMessage 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);

    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值