ContentProvider → Room + Repository

ContentProvider → Room + Repository

老写法(Java + ContentProvider)

java 复制代码
// 查询联系人(系统 ContentProvider)
Cursor cursor = getContentResolver().query(
        ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
        null, null, null, null);
while (cursor.moveToNext()) {
    String name = cursor.getString(
            cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
    String number = cursor.getString(
            cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
}
cursor.close();

自定义 ContentProvider:

java 复制代码
public class ItemProvider extends ContentProvider {
    private MyDbHelper dbHelper;

    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
                        String[] selectionArgs, String sortOrder) {
        SQLiteDatabase db = dbHelper.getReadableDatabase();
        return db.rawQuery("SELECT * FROM item", null);
    }
    // ... insert、update、delete 同样要重写
}

问题在哪里

自定义 ContentProvider 太重了------要实现 CRUD 全部六个方法,大多数项目只用其中一两个。一个简单的数据查询要通过 URI 解析、权限检查、跨进程调用,复杂度远超它提供的价值。

系统 ContentProvider(如联系人、日历)该用还得用,但自己项目里的数据没必要包装成 ContentProvider。

新写法(Room + Repository)

kotlin 复制代码
// DAO
@Dao
interface ItemDao {
    @Query("SELECT * FROM item")
    fun getAll(): Flow<List<Item>>

    @Insert
    suspend fun insert(item: Item)

    @Delete
    suspend fun delete(item: Item)
}

// Repository
class ItemRepository(private val dao: ItemDao) {
    fun getAll(): Flow<List<Item>> = dao.getAll()

    suspend fun insert(item: Item) = dao.insert(item)

    suspend fun delete(item: Item) = dao.delete(item)
}

// ViewModel
class ItemViewModel(private val repo: ItemRepository) : ViewModel() {
    val items: LiveData<List<Item>> = repo.getAll().asLiveData()

    fun insert(item: Item) {
        viewModelScope.launch(Dispatchers.IO) { repo.insert(item) }
    }
}

一句话注意

如果确实需要向其他应用暴露数据(比如你做了一个 Launcher 或输入法),ContentProvider 仍然是最佳选择。只是项目内部自己的数据读写,Room + Repository 就够了,没必要上一套 ContentProvider。

如果原来的 Provider 是被自己项目内部多个进程共享的,迁移时需要考虑 DataStore 多进程替代方案或用 MMKV(腾讯开源的高性能 KV 库)。


Java Android 老项目迁移系列,持续更新中。

相关推荐
成都大菠萝1 天前
Android Car CarProperty 车辆信号链路
android
敲代码的鱼1 天前
PDF 预览与签名批注写回 支持安卓 iOS 鸿蒙 UTS插件
android·前端·ios
时光足迹1 天前
uni-app 视频通话实战:康复师与患者视频问诊的 6 个致命 Bug 与解决方案
android·ios·uni-app
像我这样帅的人丶你还1 天前
Java 后端详解(四):分页与搜索
java·javascript·后端
她的男孩1 天前
数据权限为什么不能只靠注解?Forge 的 Mapper 层 SQL 改写源码拆解
java·后端·架构
tntxia1 天前
Mybatis的日志输入
java
亦暖筑序1 天前
Java 8老系统Browser Agent实战:三层拦截把AI操作后台变成可审计流程
java·后端·设计模式
Coffeeee1 天前
闲聊几句,Android老哥们,你们多久没做技改需求了
android·程序员·代码规范
萝卜er1 天前
Fragment 生命周期与状态恢复-《Android深水区(四)》
android
萝卜er1 天前
Intent 显式、隐式与 PendingIntent-《Android深水区(五)》
android