深入分析 Android ContentProvider (三)
创始人
2024-11-06 10:38:10

文章目录

    • 深入分析 Android ContentProvider (三)
    • ContentProvider 的高级使用和性能优化
      • 1. 高级使用场景
        • 1.1. 数据分页加载
          • 示例:分页加载
        • 1.2. 使用 Loader 实现异步加载
          • 示例:使用 CursorLoader 加载数据
        • 1.3. ContentProvider 与权限管理
          • 示例:配置权限
      • 2. 性能优化策略
        • 2.1. 缓存机制
          • 示例:使用 LruCache 进行缓存
        • 2.2. 批量操作
          • 示例:批量插入数据
        • 2.3. 使用异步操作
          • 示例:使用 AsyncTask 进行异步查询
        • 2.4. 索引优化
          • 示例:创建索引
      • 3. 总结

深入分析 Android ContentProvider (三)

ContentProvider 的高级使用和性能优化

在实际应用中,合理使用 ContentProvider 并进行性能优化是确保应用高效运行的关键。以下内容将介绍一些高级使用场景和性能优化策略。

1. 高级使用场景

1.1. 数据分页加载

对于大量数据的查询,可以通过分页加载提高效率。分页加载常用于列表视图中,以避免一次性加载所有数据导致的性能问题。

示例:分页加载

query 方法中实现分页加载:

@Override public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,                     @Nullable String[] selectionArgs, @Nullable String sortOrder) {     int limit = 20; // 每页加载的数据量     int offset = 0; // 偏移量     String limitClause = " LIMIT " + limit + " OFFSET " + offset;          Cursor cursor;     switch (uriMatcher.match(uri)) {         case EXAMPLES:             cursor = database.query(DatabaseHelper.TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder + limitClause);             break;         case EXAMPLE_ID:             cursor = database.query(DatabaseHelper.TABLE_NAME, projection, DatabaseHelper.COLUMN_ID + "=?",                     new String[]{String.valueOf(ContentUris.parseId(uri))}, null, null, sortOrder);             break;         default:             throw new IllegalArgumentException("Unknown URI: " + uri);     }     cursor.setNotificationUri(getContext().getContentResolver(), uri);     return cursor; } 

在调用端实现分页查询:

Uri uri = Uri.parse("content://com.example.provider/example"); String sortOrder = "name ASC LIMIT 20 OFFSET 0"; // 加载第一页数据 Cursor cursor = getContentResolver().query(uri, null, null, null, sortOrder); if (cursor != null) {     while (cursor.moveToNext()) {         String name = cursor.getString(cursor.getColumnIndexOrThrow("name"));         // 处理数据     }     cursor.close(); } 
1.2. 使用 Loader 实现异步加载

使用 Loader 可以在异步线程中加载数据,避免在主线程中进行耗时操作,从而保持 UI 的流畅性。CursorLoader 是一个常用的 Loader,用于 ContentProvider 的异步查询。

示例:使用 CursorLoader 加载数据

实现一个 LoaderManager.LoaderCallbacks 接口:

public class ExampleActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks {     private static final int LOADER_ID = 1;      @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_example);          getSupportLoaderManager().initLoader(LOADER_ID, null, this);     }      @NonNull     @Override     public Loader onCreateLoader(int id, @Nullable Bundle args) {         Uri uri = Uri.parse("content://com.example.provider/example");         return new CursorLoader(this, uri, null, null, null, "name ASC");     }      @Override     public void onLoadFinished(@NonNull Loader loader, Cursor data) {         // 处理加载完成的数据     }      @Override     public void onLoaderReset(@NonNull Loader loader) {         // 清理资源     } } 
1.3. ContentProvider 与权限管理

在一些安全性要求较高的场景下,合理配置 ContentProvider 的权限是非常重要的。通过权限声明和 URI 权限授予,可以确保数据访问的安全性。

示例:配置权限

AndroidManifest.xml 中声明权限,并为 ContentProvider 设置权限:

   

在代码中授予 URI 权限:

getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 

2. 性能优化策略

2.1. 缓存机制

通过缓存机制,可以减少对数据库的频繁访问,提高数据查询的效率。可以使用内存缓存或磁盘缓存来存储常用数据。

示例:使用 LruCache 进行缓存
private LruCache mMemoryCache;  public void initCache() {     final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);     final int cacheSize = maxMemory / 8;     mMemoryCache = new LruCache<>(cacheSize); }  public void addBitmapToMemoryCache(String key, Bitmap bitmap) {     if (getBitmapFromMemCache(key) == null) {         mMemoryCache.put(key, bitmap);     } }  public Bitmap getBitmapFromMemCache(String key) {     return mMemoryCache.get(key); } 
2.2. 批量操作

在对数据进行插入、更新或删除时,使用批量操作可以减少数据库的锁定次数,提高操作效率。

示例:批量插入数据
ArrayList operations = new ArrayList<>(); for (int i = 0; i < 100; i++) {     ContentValues values = new ContentValues();     values.put("name", "Example " + i);     operations.add(ContentProviderOperation.newInsert(CONTENT_URI)             .withValues(values)             .build()); } try {     getContentResolver().applyBatch("com.example.provider", operations); } catch (RemoteException | OperationApplicationException e) {     e.printStackTrace(); } 
2.3. 使用异步操作

避免在主线程中进行数据库操作,使用 AsyncTaskLoaderRxJava 等异步框架进行数据操作,确保 UI 的流畅性。

示例:使用 AsyncTask 进行异步查询
private class QueryTask extends AsyncTask {     @Override     protected Cursor doInBackground(Void... voids) {         Uri uri = Uri.parse("content://com.example.provider/example");         return getContentResolver().query(uri, null, null, null, "name ASC");     }      @Override     protected void onPostExecute(Cursor cursor) {         // 处理查询结果     } } 
2.4. 索引优化

为频繁查询的字段创建索引,可以显著提高查询效率。可以在创建表时添加索引,或者在表创建后使用 SQL 语句添加索引。

示例:创建索引
private static final String TABLE_CREATE =         "CREATE TABLE " + TABLE_NAME + " (" +         COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +         COLUMN_NAME + " TEXT);";  private static final String INDEX_CREATE =         "CREATE INDEX index_name ON " + TABLE_NAME + " (" + COLUMN_NAME + ");";  @Override public void onCreate(SQLiteDatabase db) {     db.execSQL(TABLE_CREATE);     db.execSQL(INDEX_CREATE); } 

3. 总结

通过上述高级使用场景和性能优化策略,可以更好地利用 ContentProvider 提供的数据共享和跨进程通信功能,构建高效、可靠的 Android 应用。在实际开发中,根据具体需求合理设计和优化 ContentProvider,可以大幅提升应用的性能和用户体验。

欢迎点赞|关注|收藏|评论,您的肯定是我创作的动力

在这里插入图片描述

相关内容

热门资讯

裸辞做“一人公司”,我后悔了 去年这个时候,一位以色列程序员正在东南亚旅行。他顺手把一个在脑子里转了很久的想法做成了产品,一个让任...
南京建成国内首个Pre-6G试... 4月21日,2026全球6G技术与产业生态大会在南京开幕。全息互动技术展台前,一名远在北京的工作人员...
超梵求职受邀参加“2025抖音... 超梵求职受邀参加“2025抖音巨量引擎成人教育行业生态大会”,探讨分享优质内容传播,服务万千学员。 ...
摩托罗拉Razr 2026(R... IT之家 4 月 22 日消息,摩托罗拉宣布新一代 Razr 折叠手机将于 4 月 29 日在美国发...
库克卸任,特纳斯领航:苹果新纪... 苹果首席执行官蒂姆·库克将卸任,硬件工程主管约翰·特纳斯将接任,苹果公司今天宣布此事。 库克将在夏季...