使用 SQLiteOpenHelper 和 ContentProvider 为每个应用程序用户使用单独的数据库

Use separate DB for each app user, with SQLiteOpenHelper and a ContentProvider

我的应用程序使用 SQLite 数据库,用 SQLiteOpenHelperContentProvider 包装。我在应用程序中添加了登录功能,现在 我希望每个用户只能看到自己的数据。我想实现这一点的方法是让应用程序为登录该应用程序的每个用户创建一个单独的数据库,并在数据库的文件名中使用用户的 ID。

我有这个ContentProvider:

public class MyProvider extends ContentProvider {

    //...

    @Override
    public boolean onCreate() {
    dbHelper = new MyDBHelper(getContext());
    return true;
}

我有这个SQLiteOpenHelper:

public class MyDBHelper extends SQLiteOpenHelper {

其中有这个构造函数:

public MyDBHelper(Context context) {
    super(context, DB_NAME, null, DB_VERSION);
}

到目前为止,该应用程序不能有多个用户,所以它只有一个数据库。所以 DB_NAME 总是同一个字符串。我现在试着这样设置:

private static String UID = FirebaseAuth.getInstance().getCurrentUser().getUid();
public static final String DB_NAME = String.format("data%s.db", UID);

(如您所见,我正在使用 Firebase 身份验证)

但这导致了崩溃,因为内容提供者显然是在应用启动时创建的,在用户通过身份验证之前。 (所以 user 为空。是的,我应该在尝试调用 getUid() 之前检查 user 是否为空,但这不会使这件事起作用)

所以这似乎不是正确的方法。如何根据签名用户使用不同的数据库?我可以让内容提供者在用户通过身份验证后首先创建吗?

我也可以将所有内容都保存在一个数据库中并添加一个 UID 列。但这是否足以保护不同用户的数据免受彼此的影响?此外,这将意味着更多的代码更改。

How can I use a different DB according to the signed user?

简单的解决方案是去掉 ContentProvider。使用 ContentProvider 的唯一原因是您要将此数据提供给其他应用程序。

此外,我会小心翼翼地使用 getUid() 并将其放入文件名中。您无法控制 getUid() returns,它可能有一天会包含文件名中无效的字符。

Can I make the content provider to first be created after a user has authenticated?

不,抱歉。

似乎这里正确的解决方案是不使用 ContentProviders。所以我接受了另一个答案。

但为了回答我的实际问题,对于决心让不同的数据库与一个 ContentProvider 一起工作的人,这是如何完成的:

我将自定义 SQLiteOpenDBHelper 的构造函数更改为也采用 uid:

    public MyDBHelper(Context context, String uid) {
        super(context, String.format(DB_NAME, uid), null, DB_VERSION);
        UID = uid;
    }

并且我更改了 ContentProvideronCreate,而不是创建 DBHelper。我创建了这个初始化 DBHelper 的函数:

    public void initDB(Uri uri) {
        String uid = uri.getPathSegments().get(0);
        if (dbHelper == null){
            dbHelper = new MyDBHelper(getContext(), uid);
        } else if (!uid.equals(dbHelper.UID)){
            dbHelper.close();
            dbHelper = new MyDBHelper(getContext(), uid);
        }
    }

我在 queryinsertupdatedelete 方法的开头调用此方法。

因此,只要内容提供者在数据库上执行某些操作但尚未与数据库建立现有连接,或者连接不存在,就会初始化与数据库建立连接的 DBHelper与不同用户的数据库。

这不是解决这个问题的正确方法,在某些情况下这可能会产生后果。但我不想让我提出的问题无人回答。