【问题标题】:Refresh/Reload database reference in custom ContentProvider after restore恢复后在自定义 ContentProvider 中刷新/重新加载数据库引用
【发布时间】:2011-11-22 23:01:02
【问题描述】:

我在我的应用程序中使用了 ContentProvider,除了一个小问题外,一切都很好。我有一个备份和恢复功能,将数据库备份到 SD 卡上的文件,然后可以恢复这些备份文件以覆盖当前数据库。整个过程正在运行,但是一旦恢复旧备份文件之一,ContentProvider 仍会保留对原始数据库的引用/缓存。我似乎找不到在 ContentProvider 中刷新或重新加载数据库引用的方法。我知道恢复是有效的,因为我可以使用 SQLite 编辑器查看数据库中的记录,当我关闭并重新打开应用程序时,它会显示正确的记录。

有人知道怎么做吗?有没有办法关闭并重新打开我没有看到的 ContentProvider?

【问题讨论】:

    标签: android database eclipse


    【解决方案1】:

    如果您的目标是 >= API 5,您可以通过 ContentProviderClient 获取对您的 ContentProvider 的引用,并运行特定于您的实现的方法:

    ContentResolver resolver = context.getContentResolver();
    ContentProviderClient client = resolver.acquireContentProviderClient("myAuthority");
    MyContentProvider provider = (MyContentProvider) client.getLocalContentProvider();
    provider.resetDatabase();
    client.release();
    

    将重置方法添加到您的ContentProvider 实现中:

    public void resetDatabase() {
        mDatabaseHelper.close();
        mDatabaseHelper = new MyDatabaseOpenHelper(context);
    }
    

    【讨论】:

    • 也谢谢你。这也非常有用。我必须接受以前的答案作为正确答案,因为它把我推向了正确的方向,而不必真正改变太多。谢谢!
    • client.release(); 已弃用。请改用close()
    • 如果你想删除并重新创建数据库,请参考这个。 stackoverflow.com/a/42265429/1318946
    【解决方案2】:

    您是否在内容提供程序中维护对实际SQLiteDatabase 的引用(例如在onCreate() 中调用SQLiteOpenHelper.getWritableDatabase(),然后保留该引用)?或者您是否从某个地方(例如每个提供程序方法中的助手)获取 DB 对象?

    通常,如果您只保留对助手的本地引用并根据需要在每个方法中获取可写/可读的数据库实例,那么这个问题应该会消失。如果没有,或许我们可以看看提供者代码?

    希望有帮助!

    【讨论】:

    • 我从 onCreate db = new DbAdapter(getContext()); 中的助手那里获得了参考。这就是所有示例所显示的。我考虑过在每种方法中都这样做,但这对我来说似乎效率很低而且有点慢。你不觉得吗?好吧,我想我会这样尝试,看看它是如何工作的。如果我有多个查询/更新,或者 ContentProvider 是否会正确管理它们,那不是也会留下一堆打开的数据库对象吗?
    • 看看像AlarmProvider这样的系统提供者是如何做的,作为我所说的例子。在 onCreate() 中获取助手,然后根据需要获取 db 类型。 ContentProvider 为您管理请求访问,这是使用它的原因之一。这也是我构建提供程序的方式:codesearch.google.com/#cZwlSNS7aEw/packages/apps/DeskClock/src/…
    • 啊……我明白了。我实际上正在使用一个 dbadapter 类来容纳我的助手并打开数据库。我正在从 API v7 应用程序迁移以使用新的兼容性库。我将分离助手并以这种方式尝试。我想我只是没有意识到我应该只是调用一个助手,所以我认为我正确地遵循了这些例子。嗬!谢谢!
    【解决方案3】:

    这是我的解决方案。

    public class DataProvider extends ContentProvider {
    
        private DataDbHelper dbHelper;
    
        @Override
        public boolean onCreate() {
            // nothing here
            return true;
        }
    
        private DataDbHelper getDbHelper() {
            if (dbHelper== null) {
                // initialize
                dbHelper = new DataDbHelper(getContext());
            } else if (dbHelper.getReadableDatabase().getVersion() != DataDbHelper.VERSION) {
                // reset
                dbHelper.close();
                dbHelper = new DataDbHelper(getContext());
            }
            return this.mOpenHelper;
        }
    }
    

    query(), insert(), update(), delete() 使用getDbHelper() 获取SQLiteDatabase

    如果您需要更多信息,我的 Android 应用程序的完整代码可在 here 获得。

    【讨论】:

      【解决方案4】:

      您也可以简单地使用删除方法而无需选择:

      context.getContentResolver().delete(YourProvider.CONTENT_URI, null, null);
      

      【讨论】:

      • 您对此声明有什么来源?似乎调用只会转到我对 delete() 方法的实现,不是吗?
      猜你喜欢
      • 2016-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-07
      • 2020-06-09
      • 2015-09-05
      相关资源
      最近更新 更多