我应该如何通知用户SQLite Asset Helper第一次加载数据库?

IAm*_*ale 6 android android-sqlite

我正在使用SQLite资产助手库来处理设置和升级我的应用程序数据库的肮脏工作.它工作得很好但不幸的是我还没有找到一种方法来通知用户何时库:

A)首次加载数据库(通过从\ assets\databases \文件夹中解压缩)

要么

B)升级数据库(使用\ assets\datates中升级的数据库文件中的信息)

我尝试将此代码放在我的应用程序的主Activity.onCreate()中,以为我可以在主线程上加载数据库(如果它不存在),同时用不可解雇的AlertDialog分散用户的注意力:

    File dbFile=this.getDatabasePath("gShoJMDict");
    Boolean dbExists = dbFile.exists();
    Log.i("ActivityStartScreen", String.valueOf(dbExists));

    if(!dbExists)
    {
        DialogFirstRun dialogFirstRun = new DialogFirstRun();
        dialogFirstRun.show(getSupportFragmentManager(), "dialogFirstRun");
        dialogFirstRun.setCancelable(false);
        DictHelper helper = new DictHelper(this);
        helper.getReadableDatabase();
        helper.close();
        dialogFirstRun.dismiss();
    }
Run Code Online (Sandbox Code Playgroud)

不幸的是,基于LogCat条目,SQLite资产助手会在onCreate()之前检查数据库是否存在,所以当上面的代码块运行时,数据库已经存在,因此对话框永远不会出现.

我正在使用ContentProvider,并且我已经验证我只是在query()或update()中调用getReadableDatabase().我的ContentProvider的onCreate()看起来像这样......

@Override
public boolean onCreate()
{
    // Load our database
    gdb = new JMDictHelper(getContext());
    return true;
}
Run Code Online (Sandbox Code Playgroud)

...但是尽管移动了gdb = new JMDictHelper(getContext()); 在查询()或更新()之前,SQLite资产助手库仍然可以在我通知用户之前很好地加载数据库.

在这种情况下,我可以做什么来拦截数据库的初始设置或升级,并通知用户应用程序正在忙于执行这些任务?现在,应用程序只是在那里做任何事情,直到库完成 - 这对于测试很好,因为我知道期待它,但是当我准备让应用程序上线时,我不能这样做.

Ben*_*Ben 6

万一你仍然想知道这个或其他人有这个问题,这里是我刚刚实现的类似问题的解决方案.在调用getReadableDatabase()或getWritableDatabase()之前,SQLiteAssetHelper不会复制数据库.如果在MainActivity.onCreate()之前调用其中一个方法,可能是因为您在ContentProvider的onCreate()方法中调用它.这是文档中的方法描述:

实现此目的以在启动时初始化您的内容提供程序.在应用程序启动时,应用程序主线程上的所有已注册内容提供程序都会调用此方法.它不能执行冗长的操作,否则应用程序启动将被延迟.

您应该推迟使用内容提供程序(通过查询(Uri,String [],String,String [],String),insert(Uri,ContentValues)等)来进行非常重要的初始化(例如打开,升级和扫描数据库). .延迟初始化可以使应用程序启动更快,如果提供程序不需要,则可以避免不必要的工作,并且可以阻止数据库错误(例如完整磁盘)停止应用程序启动.

如果您使用SQLite,SQLiteOpenHelper是一个有用的实用程序类,可以轻松管理数据库,并将自动推迟打开直到第一次使用.如果使用SQLiteOpenHelper,请确保避免从此方法调用getReadableDatabase()或getWritableDatabase().(相反,覆盖onOpen(SQLiteDatabase)以在首次打开数据库时初始化数据库.)

您可以对getReadableDatabase()或将您的ContentProvider的实际访问getWritableDatabase()您的来电,描述在这里.

既然您的ContentProvider没有提供帮助,您可以检查MainActivity.onCreate()中是否存在数据库,并在必要时在显示ProgressDialog时将其复制到后台线程中:

// Create an AsyncTask to copy the database in a background thread while
// displaying a ProgressDialog.
private class LoadDatabaseTask extends AsyncTask<Context, Void, Void> {
    Context mContext;
    ProgressDialog mDialog;

    // Provide a constructor so we can get a Context to use to create
    // the ProgressDialog.
    LoadDatabasesTask(Context context) {
        super();
        mContext = context;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        mDialog = new ProgressDialog(mContext);
        mDialog.setMessage(mContext.getString("Loading database..."));
        mDialog.show();
    }

    @Override
    protected Void doInBackground(Context... contexts) {
        // Copy database.
        new MyAssetHelper(contexts[0]).getReadableDatabase();
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        super.onPostExecute(result);
        mDialog.dismiss();
    }
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    // ...

    // Install databases if necessary.
    File database = getDatabasePath(DB_NAME);
    if (!database.exists()) {
        new LoadDatabaseTask(this).execute(this, null, null);
    }

    // ...
}
Run Code Online (Sandbox Code Playgroud)