ContentProvider

ContentProvider介绍:
ContentProvider是Android系统中能实现所有应用程序共享的一种数据存储方式,由于数据通常在各应用间的是互相私密的,所以此存储方式较少使用,但是其又是必不可少的一种存储方式。例如音频,视频,图片和通讯录,一般都可以采用此种方式进行存储。
其实是比较低调的一个,日常开发中使用的频率也没那三位多。它的诞生就是为了给不同应用提供内容访问,自然在我们研究的“多进程通信方式”之中。ContentProvider 封装了数据的跨进程传输,我们可以直接使用 getContentResolver() 拿到 ContentResolver 进行增删改查即可。ContentProvider 以一个或多个表(与在关系型数据库中的表类似)的形式将数据呈现给外部应用。 行表示提供程序收集的某种数据类型的实例,行中的每个列表示为实例收集的每条数据。
app提供的内容:
MySqliteHelper(创建的一个数据库,名字叫Students , 版本号是 1 )

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class MySqliteHelper extends SQLiteOpenHelper {
private static String sqlName = “Students”;
private static int version = 1;

public MySqliteHelper(Context context) {
    super(context, sqlName, null, version);
    // TODO Auto-generated constructor stub
}

@Override
public void onCreate(SQLiteDatabase db) {
    // TODO Auto-generated method stub
    db.execSQL("create table Student(id integer primary key autoincrement,name varchar(20),age varchar(10))");
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    // TODO Auto-generated method stub

}

}
MyProvider(使用UriMatcher本质上是文本过滤器,就不用手动过滤字符串了,如果用手动比较麻烦,维护性也不好)
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;

public class MyProvider extends ContentProvider{
private MySqliteHelper helper;
private SQLiteDatabase database;
private String tabName=“Student”;
private UriMatcher matcher;
private static final int STUDENT=666;
private String authority=“com.example.csdn.MyProvider”;
@Override
public boolean onCreate() {
// TODO Auto-generated method stub
helper=new MySqliteHelper(getContext());
matcher=new UriMatcher(UriMatcher.NO_MATCH);
matcher.addURI(authority, tabName, STUDENT);

    return true;
}

@Override
public Cursor query(Uri uri, String[] projection, String selection,
                    String[] selectionArgs, String sortOrder) {
    // TODO Auto-generated method stub
    int code=matcher.match(uri);
    database=helper.getReadableDatabase();
    Cursor cursor=database.query(tabName, projection, selection, null, null, null, null);
    return cursor;
}

@Override
public String getType(Uri uri) {
    // TODO Auto-generated method stub
    return null;
}

@Override
public Uri insert(Uri uri, ContentValues values) {
    // TODO Auto-generated method stub
    int code=matcher.match(uri);
    database=helper.getWritableDatabase();
    database.insert(tabName, null, values);
    //将这个值插入到tabName中,对应这个值的编号
    long studentid=database.insert(tabName, null, values);
    Uri studenturi=ContentUris.withAppendedId(uri, studentid);
    return studenturi;
}

@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
    // TODO Auto-generated method stub
    int code=matcher.match(uri);
    database=helper.getWritableDatabase();
    long studentid=database.delete(tabName, selection, selectionArgs);
    return 0;
}

@Override
public int update(Uri uri, ContentValues values, String selection,
                  String[] selectionArgs) {
    // TODO Auto-generated method stub
    int code=matcher.match(uri);
    database=helper.getWritableDatabase();
    long studentid=database.update(tabName, values, selection, selectionArgs);
    return 0;
}

}
需要在配置清单注册:(记得一定要声明authorities , 不指定这个属性的话其他应用,无法通过Uri访问你的数据库)


另一个app获取提供的数据:
通过getContentResolver();获取数据,然后使用正删改查进行操作。
import java.util.ArrayList;
import java.util.List;

import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;

public class MainActivity extends Activity implements OnClickListener {
private Button mBtn_insert;
private Button mbtn_delete;
private Button mBtn_update;
private Button mBtn_query;
private ContentResolver resovler;
private ListView mLv;
private Uri uri;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    // 字符串类型的uri 转成Uri类型
    String uriStr = "content://com.example.csdn.MyProvider/Student";
    uri = Uri.parse(uriStr);
    // 获取resolver的实例
    resovler = getContentResolver();
    initView();
}

public void initView() {
    mBtn_insert = (Button) findViewById(R.id.mBtn_insert);
    mBtn_delete=(Button) findViewById(R.id.mBtn_delete);
    mBtn_update=(Button) findViewById(R.id.mBtn_update);
    mBtn_query = (Button) findViewById(R.id.mBtn_query);
    mLv = (ListView) findViewById(R.id.lv);

    mBtn_insert.setOnClickListener(this);
    mBtn_delete.setOnClickListener(this);
    mBtn_update.setOnClickListener(this);
    mBtn_query.setOnClickListener(this);
}

@Override
public void onClick(View v) {
    // TODO Auto-generated method stub
    switch (v.getId()) {
        case R.id.mBtn_insert:
            ContentValues values = new ContentValues();
            values.put("name", "杰哥");
            values.put("age", "26");
            resovler.insert(uri, values);
            break;
        case R.id.mBtn_delete:
            resovler.delete(uri, "name=?", new String[]{"杰哥"});
            break;
        case R.id.mBtn_update:
            ContentValues contentValues=new ContentValues();
            contentValues.put("name","颖宝");
            contentValues.put("age",20);
            resovler.update(uri, contentValues, "name=?", new String[]{"杰哥"});
            break;
        case R.id.mBtn_query:
            List<String> list = new ArrayList<String>();
            Cursor cursor = resovler.query(uri, null, null, null, null);
            while (cursor.moveToNext()) {
                int nameIndex = cursor.getColumnIndex("name");
                int ageIndex = cursor.getColumnIndex("age");
                String nameStr = cursor.getString(nameIndex);
                String ageStr = cursor.getString(ageIndex);
                list.add(nameStr + ageStr);
            }
            ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
                    android.R.layout.simple_list_item_1, list);
            lv.setAdapter(adapter);
            break;
    }
}

}
这个是xml布局:

<Button
    android:id="@+id/mBtn_insert"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="增加" />

<Button
    android:id="@+id/mbtn_delete"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="删除" />

<Button
    android:id="@+id/mBtn_update"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="修改" />

<Button
    android:id="@+id/mBtn_query"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="查询" />

<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、付费专栏及课程。

余额充值