【问题标题】:Use separate DB for each app user, with SQLiteOpenHelper and a ContentProvider使用 SQLiteOpenHelper 和 ContentProvider 为每个应用程序用户使用单独的数据库
【发布时间】:2018-07-07 17:20:42
【问题描述】:

我的应用程序使用一个 SQLite DB,用 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 列。但这是否可以很好地保护不同用户的数据?此外,这将意味着更多的代码更改。

【问题讨论】:

    标签: android android-sqlite android-contentprovider android-multiple-users


    【解决方案1】:

    如何根据签名用户使用不同的数据库?

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

    另外,我会谨慎地将getUid() 放入文件名中。您无法控制 getUid() 返回的内容,并且有一天它可能包含文件名中无效的字符。

    我可以让内容提供者在用户通过身份验证后首先创建吗?

    不,抱歉。

    【讨论】:

    • 我使用的是ContentProvider,因为我使用的是CursorLoader
    • 然后也摆脱它并改用 Room。
    • 是的,绝对只使用 Room,而且我绝对建议只为每个用户使用多个表而不是整个数据库
    • @talz:无论您使用 Room、其他 ORM,还是仅使用本机 SQLite API(SQLiteOpenHelper 等),都取决于您。但是,不要使用ContentProvider 只是为了使用CursorLoader
    【解决方案2】:

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

    但要回答我的实际问题,对于那些决心让不同的 DB 与一个 ContentProvider 一起工作的人来说,可以这样做: p>

    我将自定义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 保持与 DB 的打开连接,每当内容提供者对 DB 执行某些操作但与 DB 尚不存在连接,或者连接与 DB 时,都会初始化不同的用户。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-05
      • 1970-01-01
      • 2017-12-11
      • 1970-01-01
      相关资源
      最近更新 更多