SD卡上的SQLite数据库

14

我希望在SD卡上创建一个sqlite数据库(不想使用用户的内部存储)。我熟悉OpenHelper模式:

public DatabaseFoo(Context context) {
    OpenHelper openHelper = new OpenHelper(context);
    mDb = openHelper.getWritableDatabase();
}

private static class OpenHelper extends SQLiteOpenHelper {
    public OpenHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    ...

所以如果我们想要在SD卡上创建文件,我认为我们需要使用:

public static SQLiteDatabase openOrCreateDatabase (String path, 
      SQLiteDatabase.CursorFactory factory);

但是,“factory”参数应该是什么,应该使用哪个工厂?

同时,我有点担心如果用户在使用我的应用程序时拔掉SD卡会发生什么事情。

谢谢

6个回答

11

在你的SQLiteOpenHelper构造函数中执行以下操作:

DatabaseHelper(Context context) {
        super(context, context.getExternalFilesDir(null).getAbsolutePath() + "/" + DATABASE_NAME, null, DATABASE_VERSION);
    }

这将在应用程序文件夹中的sd卡上创建数据库:/sdcard/Android/data/[your_package_name]/files。 通过这种方式,Android会将数据库视为应用程序的一部分,并在用户卸载应用程序时自动删除。

在我的应用程序中,我有一个大型数据库,它在大多数情况下不适合老式手机的内部存储器,例如HTC Desire。 它在sd卡上运行得很好,并且大多数应用程序自己会被“移动到sd卡”,因此不必担心无法访问数据库,因为应用程序本身也将不可访问。


11

我没有尝试过你描述的内容,但可能可以做到并且可能会起作用——但有一些注意事项。首先,外部存储(SD卡)不安全,因此任何其他应用程序或用户都可以读写它。其次,正如你所指出的,当它被卸载时,数据库就会消失。

由于这些缺点,你最好尝试使用内部存储数据库(默认值),它很小,可能包括指向外部数据(如图像或文件)的指针——这些数据本身可以在外部存储器上(当外部存储器不可用时,它们具有占位符或其他处理方式)。

然而,如果你想尝试,你最好重写ContextgetDatabasePath方法,例如使用自己的Application对象,然后将传递给常规的SQLiteOpenHelper。然后你就不必担心游标工厂(这是可选的,as the source confirms——如果你想走这条路,只需传递null即可)。


在应用程序或自定义ContextWrapper中重写getDatabasePath不起作用。阅读打开帮助程序源代码,我注意到该方法从未被调用,而是调用mContext.openOrCreateDatabase,它会在默认的内部存储中创建DB。因此,这个方法也应该被重写。 - Mister Smith
这里你可以找到一个可行的示例,其中重写了getDatabasePath和openOrCreateDatabase方法,适用于Android 2.2和Android 4.4。 - k3b

2
public DataBaseHelper(final Context context) {
    super(context, Environment.getExternalStorageDirectory()
    + File.separator+ MYDATABASE_NAME, null, MYDATABASE_VERSION);
}

同时,在Android清单中添加权限。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

2

那就制作你自己的平面数据库 - 大多数人内存非常小,如果用大型数据库会很麻烦。

至于“如果他们拆除SD卡”的情况 - 如果用户移除了卡,显然它将无法工作!很明显。只需检查在尝试与数据库交互时是否出现错误,如果有,请告知用户 - 问题解决。


2

Cursor 工厂用于返回自定义 Cursor 实现的实例。 通常只需使用 SQLiteCursor,此时将 null 作为工厂参数传递。


0
我建议不要将数据库放在SD卡上 - 这会显著减少卡的寿命,因为它有(虽然很大,但仍然存在)可写次数限制,并且数据库需要相当多的写操作。

1
嗨,Jeff,我想了解更多关于这个限制的信息,你能提供任何更好地描述这个问题的链接吗? - Vignesh
@Vignest:http://superuser.com/questions/17350/whats-the-life-expectancy-of-an-sd-card - SD卡写入限制。数据库使用大量写入是技术的一个事实。 - Jeff
写入次数真的是一个问题吗?自2011年8月以来,我使用我的旧Android 2.2设备及其SD卡,其中每天大约有6个插入事务的数据库。SD卡仍在正常工作,没有任何问题。 - k3b
@k3b:每天只有6个事务并不多。对于如此小型、很少使用的数据库,这只相当于8k-30k次写入。正如链接的回复所说,SD卡的写入寿命大约为100k次……因此,你的数据库可能没问题,但对于典型的(更大、更常用)数据库来说,这是一个糟糕的想法。 - Jeff
希望您可以使用提交将小写操作批量处理成更少的大写操作。 - rsaxvc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接