ContentProvider

本文详细介绍了Android中的ContentProvider组件,包括其概念、用途及与其他组件的交互方式。同时提供了具体的实现示例,如创建自定义ContentProvider的过程以及如何通过ContentResolver进行数据操作。

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

一、什么是ContentProvider

ContentProvider是Android四大组件之一
ContentProvider是一种数据包装器(发布者),它提供统一的接口对数据进行操作,调用者不用关心数据到底是如何存储的
ContentProvider主要用于不同应用程序间,不同进程间的数据共享

二、什么是ContentResolver

1、 ContentResolver是数据调用者,ContentProvider将数据发布出来后,通过 ContentResolver对象结合Uri进行调用
2、 通过 ContentResolver可以调用ContentProvider的增、删、改、查操作

三、什么是Uri

1、 通用资源标识符
2、Uri代表要操作数据的地址,每个ContentProvider发布数据时都有一个唯一的地址
3、uri:content(固定写法)://com.android.contacts(包名)/contacts(要访问资源的路径)

四、创建自定义ContentProvider的步骤

  1. 使用SQLite技术,创建好数据库和数据表;
  2. 新建类继承ContentProvider;
  3. 创建UriMatcher,定义Uri规则;
  4. 重写6个抽象方法(onCreate、insert、delete 、getType、 update、 query);
  5. 在AndroidManifest中注册Provider;
  6. ContentResolver 对ContentProvider共享的数据进行增删改查。

五、使用ContentProvider实例

  1. 在项目中创建好数据库和数据表
  2. 新建一个类继承ContentProvider,重写6个抽象方法
  3. 在AndroidManifest中注册Provider
public class MyProvider extends ContentProvider {

    private String TAG = "MyProvider";

    @Override
    public boolean onCreate() {
        Log.e(TAG, "onCreate..............");
        return false;
    }

    //重写query方法,实现查询操作
    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] strings, @Nullable String s, @Nullable String[] strings1, @Nullable String s1) {
        Log.e(TAG, "query..............");
        DBHepler dbHepler = new DBHepler(getContext(), "student_db", null, 1);
        SQLiteDatabase database = dbHepler.getWritableDatabase();
        Cursor cursor = null;
        cursor = database.query("student", strings, s, strings1, null, null, s1);
        return cursor;
    }

    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        Log.e(TAG, "getType..............");
        return null;
    }

    //重写insert方法,实现添加操作
    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues contentValues) {
        Log.e(TAG, "insert..............");

        DBHepler dbHepler = new DBHepler(getContext(), "student_db", null, 1);
        SQLiteDatabase database = dbHepler.getWritableDatabase();
        database.insert("student", null, contentValues);
        return null;
    }

    //重写delete方法,实现删除操作
    @Override
    public int delete(@NonNull Uri uri, @Nullable String s, @Nullable String[] strings) {
        Log.e(TAG, "delete..............");
        DBHepler dbHepler = new DBHepler(getContext(), "student_db", null, 1);
        SQLiteDatabase database = dbHepler.getWritableDatabase();
        database.delete("student", s, strings);
        return 0;
    }

    //重写update方法,实现更新操作
    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues contentValues, @Nullable String s, @Nullable String[] strings) {
        Log.e(TAG, "update..............");
        DBHepler dbHepler = new DBHepler(getContext(), "student_db", null, 1);
        SQLiteDatabase database = dbHepler.getWritableDatabase();
        int updateRows = 0;
        updateRows = database.update("student", contentValues, s, strings);
        return updateRows;
    }
}
 <provider
            android:enabled="true"
            android:exported="true"
            android:name=".MyProvider"
            android:authorities="com.example.studentdemo.provider" />

1.创建一个新项目,新建Activity和布局文件
2. 在布局中创建所需要的控件,并在Activity中进行定义,绑定ID,设置监听
3. 作为接受方通过resolver传递参数来实现增、删、改、查的方法

<Button
        android:id="@+id/main_test_btn"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:text="测试一下"
        android:textSize="20sp"/>

    <EditText
        android:id="@+id/main_name_et"
        android:layout_width="match_parent"
        android:layout_height="50dp" />
    <Button
        android:id="@+id/main_add_btn"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:text="添加数据"
        android:textSize="20sp"/>
    <EditText
        android:id="@+id/main_delete_et"
        android:layout_width="match_parent"
        android:layout_height="50dp" />
    <Button
        android:id="@+id/main_delete_btn"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:text="删除数据"
        android:textSize="20sp"/>
    <Button
        android:id="@+id/main_search_btn"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:text="查询"
        android:textSize="20sp"/>
    <EditText
        android:id="@+id/main_before_et"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:hint="旧的"/>
    <EditText
        android:id="@+id/main_after_et"
        android:layout_width="match_parent"
        android:layout_height="50dp" 
        android:hint="新的"/>
    <Button
        android:id="@+id/main_modify_btn"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:text="修改数据"
        android:textSize="20sp"/>
public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    private Button testBtn;
    private Button addBtn;
    private Button deleteBtn;
    private Button searchBtn;
    private Button modifyBtn;

    private EditText nameEt;
    private EditText deleteEt;
    private EditText beforeEt;
    private EditText afterEt;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bindID();
    }

    private void bindID() {
        testBtn=findViewById(R.id.main_test_btn);
        addBtn=findViewById(R.id.main_add_btn);
        deleteBtn=findViewById(R.id.main_delete_btn);
        searchBtn=findViewById(R.id.main_search_btn);
        modifyBtn=findViewById(R.id.main_modify_btn);

        nameEt=findViewById(R.id.main_name_et);
        deleteEt=findViewById(R.id.main_delete_et);
        beforeEt=findViewById(R.id.main_before_et);
        afterEt=findViewById(R.id.main_after_et);

        testBtn.setOnClickListener(this);
        addBtn.setOnClickListener(this);
        deleteBtn.setOnClickListener(this);
        searchBtn.setOnClickListener(this);
        modifyBtn.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.main_test_btn://测试
                Uri uri=Uri.parse("content://com.example.studentdemo.provider");
                ContentResolver resolver=getContentResolver();
                resolver.delete(uri,null,null);
                break;
            case R.id.main_add_btn://添加数据
                String name=nameEt.getText().toString();
                Uri uri1=Uri.parse("content://com.example.studentdemo.provider");
                ContentResolver resolver1=getContentResolver();
                ContentValues values=new ContentValues();
                values.put("name",name);
                resolver1.insert(uri1,values);
                break;
            case R.id.main_delete_btn://删除数据
                Uri uri2=Uri.parse("content://com.example.studentdemo.provider");
                ContentResolver resolver2=getContentResolver();
                resolver2.delete(uri2,"name=?",new String[]{deleteEt.getText().toString()});
                break;
            case R.id.main_search_btn://查询数据
                Uri uri3=Uri.parse("content://com.example.studentdemo.provider/student");
                Cursor cursor=getContentResolver().query(uri3,null,null,null,null);
                if (cursor!=null){
                    while (cursor.moveToNext()){
                        String sname=cursor.getString(cursor.getColumnIndex("name"));
                        Log.e( "onClick: ",sname );
                    }
                    cursor.close();
                }
                break;
            case R.id.main_modify_btn://修改数据
                String aftername=afterEt.getText().toString();
                Uri uri4=Uri.parse("content://com.example.studentdemo.provider");
                ContentResolver resolver4=getContentResolver();
                ContentValues values4=new ContentValues();
                values4.put("name",aftername);
                resolver4.update(uri4,values4,"name=?",new String[]{beforeEt.getText().toString()});
                break;
                default:
                    break;
        }
    }
}
<think>好的,用户想了解Android开发中ContentProvider的用法和示例。首先,我需要回顾ContentProvider的基本概念,它是Android四大组件之一,主要用于不同应用间的数据共享。接着,要说明它的核心作用,比如封装数据访问、提供统一接口等。 然后,用户可能需要知道如何创建自定义的ContentProvider。这包括继承ContentProvider类,实现必要的方法如query、insert、update、delete等。还需要提到在AndroidManifest.xml中注册Provider,并设置android:exported属性来控制是否对外暴露。引用中的内容提到android:exported=false可以限制仅供内部使用,这点很重要,特别是涉及安全性的问题,必须包含进去。 接下来,应该给出一个简单的示例代码,展示如何定义ContentProvider的子类,并实现各个方法。同时,示例中的UriMatcher和SQLiteOpenHelper的使用也是关键点,需要解释清楚。代码部要注意使用正确的格式,并确保语法正确。 另外,用户可能关心ContentProvider的使用场景,比如数据共享、与CursorLoader结合使用等。还要提到ContentResolver的用法,因为这是访问Provider的主要方式。需要强调线程安全,引用中提到5.4节关于线程安全的内容,应该指出在实现时需要注意同步机制,避免多线程问题。 最后,生成相关问题时要围绕用户可能进一步想知道的内容,比如如何限制访问权限、与数据库交互的细节、性能优化等。确保问题覆盖常见的使用场景和潜在的问题点,帮助用户深入理解。 现在需要检查回答是否符合系统指令,比如行内公式是否正确使用(虽然这里可能用不上,但要注意其他格式要求),独立公式是否单独成段,中文回答,以及引用标识是否正确添加。同时,确保示例代码正确,并且引用的内容自然插入到回答中,比如在讲解注册Provider时引用[^2],在讲解线程安全时引用[^1]等。 总结步骤:介绍ContentProvider的作用,创建步骤,示例代码,使用场景,安全配置,线程安全,最后生成相关问题。确保每个部都清晰,并且引用正确。</think>### ContentProvider在Android开发中的使用及示例 ContentProvider是Android四大组件之一,主要用于**跨应用数据共享**,提供标准化的数据访问接口。以下是其核心知识点: #### 一、核心作用 1. **数据封装**:将数据源(如SQLite、文件、网络)封装为统一的访问接口。 2. **跨进程通信**:通过URI标识数据路径,支持其他应用通过ContentResolver访问数据。 3. **权限控制**:通过AndroidManifest.xml定义读写权限,例如: ```xml <provider android:name=".MyContentProvider" android:authorities="com.example.provider" android:exported="false" <!-- 禁止外部访问 --> android:readPermission="android.permission.READ_DATA" android:writePermission="android.permission.WRITE_DATA"/> ``` 通过`android:exported=false`可限制仅供内部使用[^1]。 #### 二、自定义ContentProvider步骤 1. **继承ContentProvider类**并实现六个核心方法: ```java public class MyProvider extends ContentProvider { @Override public boolean onCreate() { // 初始化数据库等操作 return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // 查询数据逻辑 } // 实现insert、update、delete、getType方法 } ``` 2. **定义数据URI**: ```java private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); static { uriMatcher.addURI("com.example.provider", "books", 1); // 匹配路径:/books } ``` #### 三、数据访问示例 通过ContentResolver操作数据: ```java // 查询数据 Cursor cursor = getContentResolver().query( Uri.parse("content://com.example.provider/books"), null, null, null, null ); // 插入数据 ContentValues values = new ContentValues(); values.put("title", "Android Guide"); getContentResolver().insert(uri, values); ``` #### 四、线程安全与性能 1. **线程安全**:ContentProvider方法默认运行在主线程,需自行实现同步机制(如使用`synchronized`块)。 2. **数据库优化**:建议配合SQLiteOpenHelper管理数据库连接,避免频繁打开关闭。 #### 五、典型应用场景 1. 应用内多个模块共享同一数据库 2. 向系统提供数据(如自定义联系人存储) 3. 与SyncAdapter配合实现后台数据同步
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值