Android SQLiteOpenHelper耗时onCreate,首次运行时需要进度条

时间:2014-08-19 19:06:10

标签: android sqlite sqliteopenhelper

我的应用程序第一次运行它会创建一个数据库,在该数据库中,它会从/res/raw中的文件加载6,000行。我无法异步执行此操作,因为应用程序完全依赖于它。它在我的手机上快速运行 - 一个Moto X - 但它在我的所有模拟器中都非常慢,我担心它在较慢的设备上可能会慢一些,因此在应用程序执行之前让用户盯着空白屏幕几秒钟任何东西。

有没有办法在运行覆盖的SQLiteOpenHelper的{​​{1}}方法时放置进度条,并让它更新进度条的详细程度,并显示类似“初始化数据以供首次使用!“?

2 个答案:

答案 0 :(得分:3)

我通过在AsyncTask中启动onCreate然后仅在“AsyncTask”结尾处加载布局(或者先前已加载数据)来解决此问题。它作为加载屏幕工作得很漂亮。我按照本教程http://www.41post.com/4588/programming/android-coding-a-loading-screen-part-1(更详细地解释了详细信息)然后根据我的需要对其进行了一些更改(例如加载原始资源)。

我应该说虽然它是异步的,因为主要布局没有加载,但是用户必须等待加载完成才能继续,所以希望这意味着它会异步赢得&#39 ;根据数据库的不同,应用程序会对您造成问题。

    @Override
    protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);

       SharedPreferences sharedPref = getSharedPreferences(getString(R.string.preference_file_key), Context.MODE_PRIVATE);
       dataAddedToDB = (sharedPref.getBoolean(PXS_RXS_UPDATE, false));

       if (!dataAddedToDB) {
        new LoadViewTask(this).execute();
       } else {
        setContentView(R.layout.activity_main);
       }
    }

AsyncTask中,它会加载数据库,显示它有多远并显示您的消息,然后继续显示最后的布局。 (顺便说一句,这样做有助于锁定屏幕方向,以防止它弄乱它)。

编辑:publishProgress(counter);将任务所在的值传递给onProgressUpdate()

    private class LoadViewTask extends AsyncTask<Void, Integer, Void> {

    private Context context;
    public LoadViewTask(Context context) {
        this.context = context.getApplicationContext();
    }

    @Override
    protected void onPreExecute() {

        progressDialog = new ProgressDialog(MainActivity.this);
        progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        progressDialog.setTitle("Loading...");
        progressDialog.setMessage("Initializing data for first use!");
        progressDialog.setCancelable(false);
        progressDialog.setIndeterminate(false);

        // this counts how many line to be added to the database so it can later tell how far it has got.
        final Resources resources2 = context.getResources();
        InputStream inputStream2 = resources2.openRawResource(R.raw.rawherbaldata);
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream2));
        int lineCount = 0;

        try {
            String line;
            while ((line = reader.readLine()) != null) {
                lineCount++;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        progressDialog.setMax(lineCount);
        progressDialog.setProgress(0);
        progressDialog.show();
    }

    @Override
    protected Void doInBackground(Void... params) {
        HerbalDatabaseOpenHelper mHerbalDbHelper = new HerbalDatabaseOpenHelper(MainActivity.this);
        SQLiteDatabase db = mHerbalDbHelper.getWritableDatabase();

        int counter = 0;

        final Resources resources2 = context.getResources();
        InputStream inputStream2 = resources2.openRawResource(R.raw.rawherbaldata);
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream2));

        db.beginTransaction();
        try {
            int lineNumber = 1;
            String line;
            while ((line = reader.readLine()) != null) {

            // CODE FOR ENTERING LINE INTO DATABASE         

            // EDIT: the following keeps the task updated on where it has got to, passing the count to onProgressUpdate()
            counter++;
            publishProgress(counter);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        db.setTransactionSuccessful();
        db.endTransaction();
        db.close();

        return null;
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        progressDialog.setProgress(values[0]);
    }

    @Override
    protected void onPostExecute(Void result) {
        progressDialog.dismiss();

        SharedPreferences sharedPref = getSharedPreferences(getString(R.string.preference_file_key), Context.MODE_PRIVATE);
        pxsRxsUpdate = true;
        SharedPreferences.Editor editor = sharedPref.edit();
        editor.putBoolean(PXS_RXS_UPDATE, pxsRxsUpdate);
        editor.commit();

        // initialize the View
        setContentView(R.layout.activity_main);
    }
}

答案 1 :(得分:2)

您可以使用另一个显示进度对话框的中间活动,然后在完成后将其发送回主活动。

首先,如果数据库已经创建,你需要一个布尔值的静态方法。

然后在你的活动内onCreate在必要时给中间人打电话:

DbHelper mDbHelper;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if (!DbHelper.isDbCreated()) {
        Intent intent = new Intent(this, DbActivity.class);
        startActivity(intent);
        finish();
        return;
    }
    // Do normal stuff like instantiating the helper and so on
    mDbHelper = new DbHelper();
    ...
}

然后在这个“中间人”活动内部显示ProgressDialog并创建数据库。

完成后,隐藏对话框并返回主要活动:

mProgress.dismiss();

Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);

finish();
return;

如果正确创建了静态方法isDbCreated(),则在创建数据库之前不会显示MainActivity的内容。

修改

这是我用来检查数据库的方法。也许它会对你有所帮助。

public boolean isDbCreated() {
    String sDatabasePath = context.getDatabasePath(DB_NAME).getPath();
    SQLiteDatabase tmpDb = null;

    if (mContext.getDatabasePath(DB_NAME).exists()) {
        try {
            tmpDb = SQLiteDatabase.openDatabase(sDatabasePath, null,
                    SQLiteDatabase.OPEN_READONLY);
            tmpDb.close();
        } catch (SQLiteException e) {
            e.printStackTrace();
        }
    } else {
        Log.e(TAG, "DB file doesn't exist.");
        // If the parent dir doesn't exist, create it
        File parentDir = new File(mContext.getDatabasePath(DB_NAME).getParent());
        if (!parentDir.exists()) {
            if (parentDir.mkdirs()) {
                Log.d(TAG, "Successfully created the parent dir:" + parentDir.getName());
            } else {
                Log.e(TAG, "Failed to create the parent dir:" + parentDir.getName());
            }
        }
    }

    return (tmpDb != null);
}