系列文章目录
Android四大组件基础学习
Android四大组件基础学习之Activity-优快云博客
第一章
第二章
Android四大组件基础学习之Service-优快云博客
第三章
Android四大组件基础学习之Broadcast Receiver-优快云博客
第四章 Android四大组件基础学习之Content Provider
文章目录
目录
前言
通过一个基础案例来学习Android四大组件,一共分为4章,这是最后一章,如果有做的不好的地方、文章上的错误,或者是建议,欢迎大家在评论区或者私信我,感谢大家的包容和理解!
一、Content Provider介绍
1.Content Provider的概念
(1.1)Content Provider定义
Content Provider是Android系统中用于在不同应用之间共享数据的组件。它提供了一套标准的接口,使得其他应用能够访问和操作由该Content Provider管理的数据。
(1.2)数据模型
Content Provider通过一种类似表格的结构来组织数据,每一行代表一条记录,每一列代表一个字段。这种数据模型类似于关系数据库中的表结构。
例如,在联系人Content Provider中,每一行可能代表一个联系人,每一列可能代表联系人的姓名、电话号码、邮箱等信息。
(1.3)Uri
Uri是Content Provider中用于标识数据的统一资源标识符。它通常以content://
开头,后面跟着authority(唯一标识) 和path(资源路径)。例如,系统联系人Content Provider的Uri可能是content://contacts/people
2.Content Provider的特点
(1)不同应用间数据共享
(2)统一的访问接口
(3)抽象数据源,Content Provider可以抽象不同类型的底层数据源,如SQLite数据库、文件系统等,开发者只需关注数据的访问逻辑,而无需关心数据的实际存储方式。
二、Content Provider的方法
通过context.getContentResolver()方法获取ContentResolver的实例,来使用以下方法
ContentResolver contentResolver = context.getContentResolver();
方法名 | 描述 | 参数 |
---|---|---|
onCreate() | 在Content Provider被创建时调用,用于初始化工作,如打开数据库连接。 | 无 |
getType() | 返回指定Uri的数据的MIME类型。 | Uri uri :要查询的Uri。 |
insert() | 向Content Provider中插入一条新记录。 |
|
delete() | 从Content Provider中删除记录。 |
|
update() | 更新Content Provider中的记录。 |
|
query() | 查询Content Provider中的数据。 |
|
举个例子:
//创建ContentResolver对象
ContentResolver contentResolver = context.getContentResolver();
//创建一个 ContentValues 对象,用于存储键值对
ContentValues contentValues = new ContentValues();
//添加数据
contentValues.put("column1", value1);
contentValues.put("column2", value2);
// 通过ContentResolver向指定的内容提供者URI插入数据
// insert()方法会将ContentValues中的数据插入到指定URI对应的内容提供者中
// 并返回新插入数据的URI,该URI可以用于后续的查询、更新或删除操作
Uri insertedUri = contentResolver.insert(insertUri, contentValues);
三、Content Provider的创建及使用
假设我们需要在应用中存储用户的一些偏好设置,用户使用的用户名,并允许其他应用访问这些设置。
同样的创建包和ContentProvider类,,取名UserPreferencesProvider,URI设定为com.example.myapp.userpreferences,四章下来文件目录如下
1.编写UserPreferencesProvider,实现存储用户偏好
UserPreferencesProvider.java:
package com.example.contentProvider;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.net.Uri;
import java.util.Map;
public class UserPreferencesProvider extends ContentProvider {
//定义 ContentProvider 的唯一标识(Authority)
private static final String AUTHORITY = "com.example.myapp.userpreferences";
//创建一个UriMatcher对象,用于匹配传入的URI,NO_MATCH表示初始时不匹配任何 URI
private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
//创建SharedPreferences对象,用于存储和检索键值对
private SharedPreferences sharedPreferences;
//静态块,类加载时执行
static {
//URI的授权部分,匹配preferences,匹配成功时返回的整数值
//content://com.example.myapp.userpreferences/preferences
uriMatcher.addURI(AUTHORITY, "preferences", 1);
}
public UserPreferencesProvider() {
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return 0;
}
@Override
public String getType(Uri uri) {
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
return null;
}
//初始化方法
@Override
public boolean onCreate() {
//获取名为 user_preferences 的 SharedPreferences 对象
//MODE_PRIVATE 表示 SharedPreferences 数据只能被本应用访问
sharedPreferences = getContext().getSharedPreferences("user_preferences", Context.MODE_PRIVATE);
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
//匹配传入的URI
int match = uriMatcher.match(uri);
if (match == 1) {
//查询所有偏好设置
//MatrixCursor是游标(Cursor)的一个实现类,模拟数据库表
MatrixCursor cursor = new MatrixCursor(new String[]{"key", "value"});
//将偏好设置复制到Map类allEntries
Map<String, ?> allEntries = sharedPreferences.getAll();
for (Map.Entry<String, ?> entry : allEntries.entrySet()) {
cursor.addRow(new Object[]{entry.getKey(), entry.getValue().toString()});
}
return cursor;
}
return null;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
return 0;
}
}
2.在 LoginActivity 中使用 Content Provider 存储用户偏好设置
LoginActivity.java:
package com.example.activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.ContentInfo;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import com.example.service.LoginStatusService;
public class LoginActivity extends AppCompatActivity {
private EditText etUsername, etPassword; //用户名、密码
private Button btnLogin; //登录按钮
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login); //设置布局文件(关联activity_login.xml与LoginActivity)
etUsername = findViewById(R.id.et_username); //将变量与XML中组件关联
etPassword = findViewById(R.id.et_password);
btnLogin = findViewById(R.id.btn_login);
btnLogin.setOnClickListener(new View.OnClickListener() { //为按钮设置点击事件监听器
@Override
public void onClick(View v) {
String username = etUsername.getText().toString().trim();
String password = etPassword.getText().toString().trim();
ContentResolver contentResolver = getContentResolver();
//uri
Uri uri = Uri.parse("content://com.example.myapp.userpreferences/preferences");
ContentValues contentValues = new ContentValues();
//存储当前用户的用户名
contentValues.put("key", "username");
contentValues.put("value", username);
contentResolver.insert(uri, contentValues);
contentValues.clear();
if (!username.isEmpty() && !password.isEmpty()) { //当用户名与密码不为空时
//创建一个从 LoginActivity 跳转到 MainActivity 的意图(Intent)
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
intent.putExtra("username", username); // 将用户名传递给下一个 MainActivity
startActivity(intent); // 跳转到 MainActivity
finish(); // 关闭当前 LoginActivity
} else {
Toast.makeText(LoginActivity.this, "用户名和密码不能为空", Toast.LENGTH_SHORT).show();
}
// 使用startService启动服务LoginStatusService
startService(new Intent(LoginActivity.this, LoginStatusService.class));
}
});
}
}
3.不要忘了在清单文件注册
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<!-- 添加检测网络状态权限 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Activity"
tools:targetApi="31">
<provider
android:name="com.example.contentProvider.UserPreferencesProvider"
android:authorities="com.example.myapp.userpreferences"
android:enabled="true"
android:exported="true"></provider>
<receiver
android:name="com.example.broadcastReceiver.NetworkStateReceiver"
android:enabled="true"
android:exported="true" />
<service
android:name="com.example.service.LoginStatusService"
android:enabled="true"
android:exported="true" />
<activity
android:name=".LoginActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".MainActivity"
android:exported="false" />
</application>
</manifest>
4.核心作用:允许其他应用访问数据,举例
//创建ContentResolver对象
ContentResolver contentResolver = getContentResolver();
//使用Uri
Uri uri = Uri.parse("content://com.example.myapp.userpreferences/preferences");
//查询
Cursor cursor = contentResolver.query(uri, null, null, null, null);
if (cursor != null) {
//遍历输出
while (cursor.moveToNext()) {
String key = cursor.getString(cursor.getColumnIndex("key"));
String value = cursor.getString(cursor.getColumnIndex("value"));
Log.d("UserPreferences", key + ": " + value);
}
//关闭游标
cursor.close();
}
四、总结
感谢大家的观看与支持,这个系列文章完结了,后续我会补充相关内容,持续更新自己的学习过程,希望能给大家提供帮助,下期文章见!