Android - 首次运行时解析文件所需的一般建议

时间:2013-02-03 14:10:36

标签: java android database performance

我有一个应用程序,当你加载它时,它会显示6个按钮。第6个按钮需要可视化一些数据。此数据以JSON格式存储在我的/raw文件夹中的txt文件中。数据大小为600kb,但目前解析并存储在数据库中大约需要3分钟。这个想法是,一旦它在数据库中,它的读取和使用数据就会更高效,更快,而不是每次都直接从文件中读取数据。

我最初创建了应用程序,以便从我的REST服务器下载数据,然后将其存储在数据库中,但后来认为将文件与应用程序一起发送会快得多。但是,它仍然很慢。

我正在寻找有关如何加快此文件解析并使用户体验更好的建议。目前,他们第一次进入此部分,出现ProgressDialog,他们必须等待几分钟(我的HTC Desire上3分钟)才能完成所有这些文件解析,然后才能使用特征。进度对话框就在那里,直到完成为止,用户无法执行任何其他操作。它不理想! 我曾考虑过只在后台的一个单独的线程中运行应用程序启动时的文件处理,没有进度条,所以它对用户显得无声,但是,如果他们选择按钮进入该部分,应用程序加载后立即依赖此数据,这将导致更多问题,因为文件处理可能尚未完成。

也许我可以添加一些带有大量文本的“教学”弹出框,这样当他们通读它们时,文件处理就完成了。但是,我不确定添加到应用程序的价值。它很直接使用!

有人可以在这里给我一个更好的策略建议吗?另外,我认为3分钟解析600kb的JSON有点太长了吗?也许我的逻辑不如它应该有效。

以下是主题的开头:

private boolean parseFile() {
    dialog = ProgressDialog.show(activity,
             "Progress Title",
             "Progress body",
             true);
    ReadDataThread unt = new ReadDataThread();
    unt.start();
    return true;
}

private class ReadDataThread extends Thread {
    @Override
    public void run() {
        InputStream is = activity.getResources().openRawResource(R.raw.dbdata);
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        try {
            StringBuilder sb = new StringBuilder();
            sb.append(reader.readLine());
            sortAndStore(sb.toString());
        } catch (IOException e) {
            Log.e(Constants.TAG, "Error reading data");
            e.printStackTrace();
        }
        handler.sendEmptyMessage(0);
    }

    private final Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (dialog.isShowing())
                dialog.dismiss();
            Toast.makeText(activity, "Finished reading data", Toast.LENGTH_SHORT).show();
        }
    };
}

你会注意到它调用了一个名为sortAndStore的方法,它在这里:

@Override
public boolean sortAndStore(String raw) {
    boolean returnCode=false;
    ContentValues initialValues = new ContentValues();

    try {
        JSONObject f = new JSONObject(raw);
        JSONArray jsonArr = f.getJSONArray("stops");
        int arrSize=jsonArr.length();
        for(int i=0; i<arrSize; i++) {              
            initialValues.put("name", jsonArr.getJSONObject(i).getString("name"));
            initialValues.put("lat", jsonArr.getJSONObject(i).getString("lat"));
            initialValues.put("lng", jsonArr.getJSONObject(i).getString("lng"));
            initialValues.put("StopNumber", jsonArr.getJSONObject(i).getString("StopNumber"));
            initialValues.put("Route", jsonArr.getJSONObject(i).getString("Route"));
            initialValues.put("Type", jsonArr.getJSONObject(i).getString("Type"));

            //Add data to DB
            DBHelper db = new DBHelper(activity);
            returnCode = db.addData(initialValues, DBHelper.DBTableName);
        }
    } catch (JSONException e) {
        returnCode=false;
        e.printStackTrace();
    }
    return returnCode;
}

我还使用名为DBHelper的DatabaseHelper类来处理数据库内容。 DBHelper.addData()方法在此处:

public boolean addData(ContentValues initialValues, String tableName) {
    openDatabase();
    long returnCode = db.insert(tableName, "ID", initialValues);
    closeDatabase();
    return (returnCode == -1 ? false:true);
}

那么,根据以上数据,有人能为此提出更好的策略吗?是否有更高效的文件I / O代码,或者可能是一些UI技巧,给用户一种印象,即处理所花费的时间比实际更少?

谢谢。

3 个答案:

答案 0 :(得分:0)

我认为你展示了在角落某处的固定区域的进展,如动作栏或其他等等。进度可能会显示你的应用程序全局进度。然后,用户将知道正在进行的工作,您可以让用户在没有您的数据的情况下实现某些操作。

答案 1 :(得分:0)

如前所述,您可以使用预先填充的数据库发送应用程序。查看这篇文章,它非常简单明了Using your own SQLite database in Android applications

答案 2 :(得分:0)

我通过简单地使用statements而不是单独的insert语句来修复此问题。

例如,在for()循环之前,我获得了数据库并启动了事务。然后我像往常一样经历了循环。循环之后,我只是关闭了事务,这启用了批量事务。

插入现在需要几秒钟!!