【Android从零单排系列四十一】《Android数据存储方式-ContentProvider》

2023-07-17 20:35:55 浏览数 (2)

前言

小伙伴们,在上文中我们介绍了Android数据存储中的SharedPreference,本文我们继续盘点介绍Android开发中的另一个数据存储方式ContentProvider。

一 ContentProvider基本介绍

ContentProvider是Android中的一个组件,用于在应用程序间共享数据。它可以封装底层的数据存储细节,并提供统一的接口来进行数据的读取、插入、更新和删除操作。通过ContentProvider,应用程序可以安全地访问其他应用程序的数据,实现了数据共享和交互。

二 ContentProvider使用方法

  1. 定义ContentProvider:首先,在你的应用程序中创建一个类,继承自ContentProvider。在该类中,你需要实现一些必要的方法,如onCreate()query()insert()update()delete(),以提供对数据的访问和操作。
  2. 注册ContentProvider:在AndroidManifest.xml文件中,将你的ContentProvider注册为一个组件。通过<provider>元素来配置ContentProvider的信息,包括名称、权限等。同时,也可以定义多个URI来定位不同类型的数据。
  3. 数据访问权限配置:如果需要限制其他应用程序对数据的访问,可以在AndroidManifest.xml文件中为ContentProvider声明相应的权限。
  4. 内容解析器操作:在客户端应用程序中,使用内容解析器(ContentResolver)来与ContentProvider进行交互。内容解析器提供了一套方法,如query()insert()update()delete(),用于查询、插入、更新和删除数据。
    • 查询数据:使用query()方法查询数据,指定要访问的URI、投影(即要返回的列)、选择条件、排序顺序等参数。该方法返回一个Cursor对象,可以通过该对象获取查询结果。
    • 插入数据:使用insert()方法向ContentProvider插入数据,指定要插入的URI和要插入的值。该方法返回一个表示新插入行的URI。
    • 更新数据:使用update()方法更新ContentProvider中的数据,指定要更新的URI、要更新的值以及选择条件。该方法返回受影响的行数。
    • 删除数据:使用delete()方法从ContentProvider中删除数据,指定要删除的URI和选择条件。该方法返回删除的行数。

三 ContentProvider常见属性及方法

常见属性(Attributes):

  1. android:authorities:用于在AndroidManifest.xml文件中指定ContentProvider的授权信息,标识ContentProvider提供数据的特定权限。
  2. android:exported:表示是否允许其他应用程序访问该ContentProvider。默认情况下为false,只有同一应用程序内的组件可以访问此ContentProvider。
  3. android:permission:指定访问ContentProvider所需的权限。通过定义适当的权限,可以对ContentProvider进行访问控制。

常见方法(Methods):

  1. onCreate():在创建ContentProvider时调用,通常用于执行初始化操作,如数据库的打开和连接等。
  2. query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder):用于查询数据。参数包括要访问的URI、要返回的列(投影)、选择条件、选择参数和排序顺序。返回一个Cursor对象,可以使用它来获取查询结果。
  3. insert(Uri uri, ContentValues values):用于向ContentProvider插入数据。参数包括要插入的URI和要插入的值。返回一个表示新插入行的URI。
  4. update(Uri uri, ContentValues values, String selection, String[] selectionArgs):用于更新ContentProvider中的数据。参数包括要更新的URI、要更新的值和选择条件。返回受影响的行数。
  5. delete(Uri uri, String selection, String[] selectionArgs):用于从ContentProvider中删除数据。参数包括要删除的URI和选择条件。返回删除的行数。
  6. getType(Uri uri):用于获取指定URI的MIME类型。MIME类型用于描述数据的媒体类型,例如"image/jpeg"、"text/plain"等。
  7. 其他辅助方法:除了上述方法外,还可以根据需求实现其他自定义方法来完成特定的数据操作,这些方法可以直接在ContentProvider中定义和调用。

四 ContentProvider简单案例

创建ContentProvider类:

代码语言:javascript复制
public class MyContentProvider extends ContentProvider {

    // 声明常量,用于定义URI和数据库表信息
    private static final String AUTHORITY = "com.example.mycontentprovider";
    private static final String TABLE_NAME = "mytable";
    public static final Uri CONTENT_URI = Uri.parse("content://"   AUTHORITY   "/"   TABLE_NAME);

    // 数据库帮助类
    private DatabaseHelper dbHelper;

    @Override
    public boolean onCreate() {
        // 初始化数据库帮助类
        dbHelper = new DatabaseHelper(getContext());
        return true;
    }

    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
        // 查询数据
        SQLiteDatabase db = dbHelper.getReadableDatabase();
        Cursor cursor = db.query(TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder);
        if (cursor != null) {
            cursor.setNotificationUri(getContext().getContentResolver(), uri);
        }
        return cursor;
    }

    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        // 获取MIME类型
        return null;
    }

    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
        // 插入数据
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        long id = db.insert(TABLE_NAME, null, values);
        getContext().getContentResolver().notifyChange(uri, null);
        return ContentUris.withAppendedId(CONTENT_URI, id);
    }

    @Override
    public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
        // 删除数据
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        int count = db.delete(TABLE_NAME, selection, selectionArgs);
        getContext().getContentResolver().notifyChange(uri, null);
        return count;
    }

    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
        // 更新数据
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        int count = db.update(TABLE_NAME, values, selection, selectionArgs);
        getContext().getContentResolver().notifyChange(uri, null);
        return count;
    }
}

创建DatabaseHelper类:

代码语言:javascript复制
public class DatabaseHelper extends SQLiteOpenHelper {

    private static final String DATABASE_NAME = "mydatabase.db";
    private static final int DATABASE_VERSION = 1;
    private static final String CREATE_TABLE_SQL = "CREATE TABLE mytable (_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)";

    public DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_TABLE_SQL);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // 数据库升级操作
    }
}

注册ContentProvider: 在AndroidManifest.xml文件中添加如下代码,注册ContentProvider:

代码语言:javascript复制
<provider
    android:name=".MyContentProvider"
    android:authorities="com.example.mycontentprovider" />

使用ContentProvider: 可以使用内容解析器(ContentResolver)来与ContentProvider进行交互,以下是一些示例代码:

查询数据:

代码语言:javascript复制
String[] projection = {"_id", "name"};
String selection = null;
String[] selectionArgs = null;
String sortOrder = null;

Cursor cursor = getContentResolver().query(MyContentProvider.CONTENT_URI, projection, selection, selectionArgs, sortOrder);
if (cursor != null) {
	// 处理查询结果
    while (cursor.moveToNext()) {
        int idIndex = cursor.getColumnIndex("_id");
        int nameIndex = cursor.getColumnIndex("name");
        int id = cursor.getInt(idIndex);
        String name = cursor.getString(nameIndex);
        // 打印数据
        Log.d("MyContentProvider", "id: "   id   ", name: "   name);
    }
    cursor.close();
}

插入数据:

代码语言:javascript复制
ContentValues values = new ContentValues();
values.put("name", "John");

Uri uri = getContentResolver().insert(MyContentProvider.CONTENT_URI, values);

更新数据:

代码语言:javascript复制
ContentValues values = new ContentValues();
values.put("name", "Michael");

String selection = "_id=?";
String[] selectionArgs = {"1"};

int count = getContentResolver().update(MyContentProvider.CONTENT_URI, values, selection, selectionArgs);

删除数据:

代码语言:javascript复制
String selection = "_id=?";
String[] selectionArgs = {"1"};

int count = getContentResolver().delete(MyContentProvider.CONTENT_URI, selection, selectionArgs);

通过这个简单的ContentProvider案例,你可以了解到创建、注册和使用ContentProvider的基本步骤。

五 总结

  1. 数据共享:ContentProvider提供了一种有效的方式来共享数据,使得不同的应用程序可以访问和操作相同的数据集。这样可以提高应用之间的互操作性和数据共享的灵活性。
  2. 数据安全性:ContentProvider具有权限控制机制,可以限制其他应用对数据的访问权限。这样可以确保敏感数据不被未经授权的应用程序获取,提高数据的安全性。
  3. 数据管理:ContentProvider提供了CRUD(创建、读取、更新、删除)操作的接口,可进行数据的增删改查操作。这样可以方便地管理和维护数据集。
  4. 效率和性能:通过ContentResolver和ContentProvider进行数据交互,可以避免直接操作数据库或文件系统,从而提高数据访问的效率和性能。
  5. 学习曲线:使用ContentProvider需要掌握相关的API和概念,对开发者来说可能存在一定的学习曲线。但一旦掌握了ContentProvider的使用方法,可以极大地提升应用程序的功能和灵活性。
  6. 可维护性:使用ContentProvider可以将数据管理的逻辑与UI层分离,使得代码结构更清晰、可维护性更高。这对于大型应用程序和团队协作开发非常重要。

总体而言,ContentProvider是Android中一个功能强大且重要的组件,它提供了一种标准化的方式来实现不同应用之间的数据共享和访问。合理利用ContentProvider能够增加应用的灵活性、安全性和可维护性,从而提升用户体验和开发效率。

0 人点赞