欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 能源 > 【Android】安卓四大组件之ContentProvider知识总结

【Android】安卓四大组件之ContentProvider知识总结

2024/10/25 11:19:21 来源:https://blog.csdn.net/Patrick_yuxuan/article/details/140890237  浏览:    关键词:【Android】安卓四大组件之ContentProvider知识总结

文章目录

  • Uri
    • 介绍
    • 组成
  • ContentResolver
    • 用法
    • 获取对象
    • 增删改查
    • 读取联系人
      • 获取权限
      • 配置ListView
  • ContentProvider
    • 方法
    • 步骤
      • 1、注册
      • 2、继承
        • onCreate
        • UriMatcher
        • insert
        • delete
        • update
        • query
        • getType
  • ContentProvider与ContentResolver

Uri

介绍

统一资源标识符(URI)是一种用于标识资源的字符串。它可以是一个网址、文件路径、或其他形式的资源定位符。在Android中,URI通常用于访问内容提供者(Content Provider)提供的数据。

举例:

  1. 获取设备上存储的所有图片

    content://media/internal/images
    
  2. 获取设备上所有联系人信息

    content://contacts/people/
    
  3. 获取ID为45的单个联系人信息

    content://contacts/people/45
    

在Java中,可以通过Uri.parse方法将字符串URI转换为Uri对象。

Uri uri = Uri.parse("content://contacts/people/45");

组成

  1. Scheme
    • 采用前缀 content://,表示这是一个内容提供者的 Uri
    • 例如:content://
  2. Authority
    • 通常采用应用程序的包名,这样可以确保其唯一性。
    • 例如:com.example.provider
  3. Path
    • 指定数据或资源的路径,可以包含具体的表名、资源名以及其他标识符。
    • 例如:/student/1

image-20240730170024367

ContentResolver

ContentResolver 是 Android 框架提供的一个类,用于与内容提供者(Content Provider)交互,提供了一系列增删改查的方法对数据进行操作,这些方法以Uri的形式对外提供数据

image-20240730165724424

用法

ContentResolver为应用程序提供了统一的接口来访问不同的ContentProvider

获取对象

使用getContentResolver()方法获取ContentResolver对象:

ContentResolver contentResolver = getContentResolver();

增删改查

  1. Uri insert(Uri uri, ContentValues values);
    

    插入新数据,并返回新插入数据的URI。

    • ContentValues对象,包含了要插入的数据键值对
  2. int delete(Uri uri, String selection, String[] selectionArgs);
    

    删除匹配条件的数据,并返回删除的行数。

    • selection: SQL WHERE 子句的筛选条件(不包括 WHERE 关键字)。用来确定哪些行会被删除。
    • selectionArgs: 选择条件的参数数组。用于替代selection中占位符(?
  3. int update(Uri uri, ContentValues values, String selection, String[] selectionArgs);
    

    更新匹配条件的数据,并返回更新的行数。

  4. Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder);
    

    查询数据,并返回一个Cursor对象。

    • projection: 指定你要返回的列。如果你想返回所有列,可以传入null
    • sortOrder: 指定排序的方式。

读取联系人

获取通讯录的数据

使用 ContentResolver 来访问系统通讯录中的数据

获取权限

在AndroidMainfest获取权限

<uses-permission android:name="android.permission.READ_CONTACTS" />

配置ListView

在MainActivity中配置ListView

public class MainActivity extends AppCompatActivity {// ArrayAdapter用于在ListView中显示联系人列表ArrayAdapter<String> adapter;// 存储联系人名称和电话号码的列表List<String> contactsList = new ArrayList<>();// 获取ListViewprivate ListView listView;// 设置布局,请求权限,初始化ListView和Adapter。@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);listView = findViewById(R.id.contacts_view);adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, contactsList);listView.setAdapter(adapter);// 检查是否已经获得了读取联系人的权限if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {// 如果没有,请求该权限ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS}, 1);} else {// 如果已经获得,直接读取联系人readContacts();}}// 没有权限弹出对话框:如果权限被授予,读取联系人;否则显示提示信息@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);// 检查是否是READ_CONTACTS权限的请求结果if (requestCode == 1) {// 检查权限是否被授予if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {// 如果被授予,读取联系人readContacts();} else {// 如果未被授予,显示提示信息Toast.makeText(this, "联系人权限获取失败", Toast.LENGTH_SHORT).show();}}}// 查询并读取设备上的联系人列表。将查询结果添加到contactsList中,并更新Adapter以显示结果。private void readContacts() {Cursor cursor = null;try {// 查询联系人数据cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);if (cursor != null) {// 遍历查询结果while (cursor.moveToNext()) {// 获取联系人名称和电话号码的列索引int nameIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME);int numberIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);// 检查列索引是否有效if (nameIndex != -1 && numberIndex != -1) {// 获取联系人名称和电话号码String displayName = cursor.getString(nameIndex);String number = cursor.getString(numberIndex);// 将名称和号码组合后添加到列表contactsList.add(displayName + "\n" + number);}}// 更新Adapter以显示新的联系人列表adapter.notifyDataSetChanged();}} catch (Exception e) {e.printStackTrace();} finally {// 关闭Cursor,释放资源if (cursor != null) {cursor.close();}}}
}

ContentProvider

内容提供者(Content Provider)是 Android 四大组件之一(Activity、Service、Broadcast Receiver、Content Provider)。它用于在不同的应用之间共享数据,尤其是在进程间通信(IPC)中起着关键作用。内容提供者通过一层中介来控制数据访问,从而确保隐私数据的安全性。

内容提供者本身并不直接存储数据,它只是定义了数据的访问接口。数据的实际存储方式包括文件存储,SharedPreferences 存储,SQLite 数据库存储

方法

创建一个自定义的 ContentProvider 类继承ContentProvider涉及实现一些关键的方法

image-20240730191342740

  1. onCreate() 方法:用于初始化 ContentProvider通常会执行一些初始化操作,比如设置数据库的连接等
  2. getType() 方法:返回给定 Uri 的 MIME 类型,以便系统知道如何处理数据
  3. insert() 方法:用于向 ContentProvider 中插入数据
  4. update() 方法:用于更新 ContentProvider 中的数据
  5. delete() 方法:用于删除 ContentProvider 中的数据
  6. query() 方法:用于查询 ContentProvider 中的数据

步骤

1、注册

创建一个ContentProvider类,as会自动在AndroidManifest.xml中注册

image-20240731210346399

image-20240731210703600

	<providerandroid:name=".MyContentProvider"android:authorities="com.example.sqlitedatabasepractice_731"android:enabled="true"android:exported="true"></provider>

image-20240731201246656

2、继承

继承了ContentProvider,得到了6个要重写的方法

onCreate
	private SQLiteDatabase db;// 初始化public boolean onCreate() {// 这里是根据自定义的UserDBHelper类的自定义构造方法创建一个UserDBHelper类的对象// 然后调用其方法获取SQLiteDatabase类的对象UserDBHelper dbHelper = new UserDBHelper(getContext());db = dbHelper.getWritableDatabase();return true;}
UriMatcher

用于根据 URI 来匹配请求,帮助 ContentProvider 解析 URI,并确定应该执行的操作或返回的数据

// UriMatcher用于URI的匹配
private static UriMatcher uriMatcher;
// 静态代码块,初始化 UriMatcher 实例和添加匹配规则
static {// 为UriMatcher添加匹配规则uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);// 添加匹配规则,匹配所有以 BASE_PATH 结尾的 URIuriMatcher.addURI(AUTHORITY, BASE_PATH, USER_DIR);// 添加匹配规则,匹配以 BASE_PATH 结尾,后跟一个 ID 的 URIuriMatcher.addURI(AUTHORITY, BASE_PATH + "/#", USER_ITEM);
}
insert
public Uri insert(Uri uri, ContentValues values) {// 插入一条新记录long id = db.insert(UserDBHelper.TABLE_NAME, null, values);// 构造新记录的URI并用来返回Uri insertedUri = Uri.withAppendedPath(CONTENT_URI, String.valueOf(id));return insertedUri;}
delete
 public int delete(Uri uri, String selection, String[] selectionArgs) {int match = uriMatcher.match(uri);int count = 0;switch (match) {case USER_DIR:// 删除满足条件的所有记录count = db.delete(UserDBHelper.TABLE_NAME, selection, selectionArgs);break;case USER_ITEM:// 删除指定ID的记录String id = uri.getLastPathSegment();count = db.delete(UserDBHelper.TABLE_NAME, "id = ?", new String[]{id});break;}return count;}
update
 public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {int count = 0;switch (uriMatcher.match(uri)) {case USER_DIR:// 更新满足条件的所有记录count = db.update(UserDBHelper.TABLE_NAME, values, selection, selectionArgs);break;case USER_ITEM:// 更新指定ID的记录String id = uri.getLastPathSegment();count = db.update(UserDBHelper.TABLE_NAME, values, "id = ?", new String[]{id});break;}return count;}
query
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {Cursor cursor = null;switch (uriMatcher.match(uri)) {case USER_ITEM:// 查询指定ID的记录String id = uri.getLastPathSegment();cursor = db.query(UserDBHelper.TABLE_NAME, projection, "id = ?", new String[]{id}, null, null, sortOrder);break;case USER_DIR:// 查询所有记录cursor = db.query(UserDBHelper.TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder);break;}return cursor;}
getType
public String getType(Uri uri) {// MINE类型说明// 字符串取值,让ANDROID系统知道处理的是整体数据还是单条数据// 特点:1.以vnd开头// 2.如果Uri以路径形式结尾,后面接android.cursor.dir/,返回的是整个数据表的MIME类型//   如果Uri以ID形式结尾,后面接android.cursor.item/,返回的是单个数据项的MIME类型// 3.最后接的内容是: vnd.<authority>.<path>switch (uriMatcher.match(uri)) {case USER_DIR:// 返回整个数据表的MIME类型return "vnd.android.cursor.dir/vnd." + AUTHORITY + "." + BASE_PATH;case USER_ITEM:// 返回单个数据项的MIME类型return "vnd.android.cursor.item/vnd." + AUTHORITY + "." + BASE_PATH;default:return null;}}

ContentProvider与ContentResolver

ContentResolver间接调用ContentProvider

ContentProvider操作自己的DataBase数据库

ContentResolver 间接调用 ContentProvider

  • ContentResolver 是用于访问和管理数据的工具,它将操作请求(如 insert(), update(), delete(), query())发送到对应的 ContentProvider
  • ContentResolver 通过 URI 定位到具体的 ContentProvider,并调用其方法来执行实际的数据操作。

ContentProvider 操作自己的数据库

  • ContentProvider 实现了对数据的 CRUD 操作,它会直接与应用程序的数据库进行交互,执行插入、更新、删除和查询等操作。
  • ContentProvider 在这些操作中使用数据库访问对象(如 SQLiteDatabase),并根据 URI 和其他参数来确定需要操作的数据。

比如:

delete() 方法处理删除请求,通过 ContentResolver 转发到具体的 ContentProvider 实现,执行删除操作并返回删除的记录数。

当你在自定义的 ContentProvider 中实现 delete() 方法时,它需要接收来自其他应用程序通过 ContentResolver 传递的删除请求。你需要根据传递的 URI 和选择条件删除数据库中的记录,并返回删除的记录数

ContentProvider` 实现了对数据的 CRUD 操作,它会直接与应用程序的数据库进行交互,执行插入、更新、删除和查询等操作。

  • ContentProvider 在这些操作中使用数据库访问对象(如 SQLiteDatabase),并根据 URI 和其他参数来确定需要操作的数据。

比如:

delete() 方法处理删除请求,通过 ContentResolver 转发到具体的 ContentProvider 实现,执行删除操作并返回删除的记录数。

当你在自定义的 ContentProvider 中实现 delete() 方法时,它需要接收来自其他应用程序通过 ContentResolver 传递的删除请求。你需要根据传递的 URI 和选择条件删除数据库中的记录,并返回删除的记录数



感谢您的阅读
如有错误烦请指正


版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com