1

我已经对我的 SQLite 数据库上的 IO 进行了一些测量。从这个数据库加载一些对象大约需要 6 秒。我有一个扩展 Asynctask 的类,这个类的工作是加载我数据库中的最后 10 个条目。这个类是这样构造的:

import View.CustomAdapter;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.util.Log;
import android.view.*;

public class LoadCases extends AsyncTask<String, Integer, ArrayList<Case>> {

    ProgressBar progressBar;
    ArrayList<Case> lastTenCases; 
    CustomAdapter cAdapter; 
    Context context;
    ListView lastCases;
    DatabaseHandler db;
    TextView loading;
    int options;

    public LoadCases(ProgressBar progressBar, Context context, ListView lastCases, TextView loading, ArrayList<Case> lastTenCases) {
        this.progressBar = progressBar;
        this.context = context;
        this.lastCases = lastCases;
        this.loading = loading;
        this.lastTenCases = lastTenCases;
        db = new DatabaseHandler(context);
    }

    public void onPreExecute() {
        progressBar.incrementProgressBy(1);
    }


    @Override
    protected ArrayList<Case> doInBackground(String... params) {
        long start = System.nanoTime();
        lastTenCases = db.getAllCases(10);
        long end = System.nanoTime();
        Log.d("TIME TO LOAD CASES FROM BASE: ", Long.toString((end-start)/1000000000)); 
        return lastTenCases;
    }

    public void onPostExecute(ArrayList<Case> result) {
        progressBar.setVisibility(View.GONE);
        loading.setVisibility(View.GONE);
        cAdapter = new CustomAdapter(context, lastTenCases);    
        cAdapter.notifyDataSetChanged();
        lastCases.setAdapter(cAdapter); 

} }

如您所见,测量是在我调用该方法之前完成的getAllCases(10)

long start = System.nanoTime();
lastTenCases = db.getAllCases(10);
long end = System.nanoTime();
Log.d("TIME TO LOAD CASES FROM BASE: ", Long.toString((end-start)/1000000000)); 

正如我之前提到的,这将给我大约 6 秒的时间从数据库中加载 10 个案例。

现在,转到getAllCases方法

public ArrayList<Case> getAllCases(int take) {

    ArrayList<Case> caseList = new ArrayList<Case>();
    String selectQuery = "SELECT  *, (strftime('%s', DATE) * 1000) AS DATENOW FROM " + TABLE_CASES + " ORDER BY " + DATE + " DESC LIMIT " + Integer.toString(take) + " ;";

    SQLiteDatabase db = this.getWritableDatabase();
    Cursor cursor = db.rawQuery(selectQuery, null);

    // looping through all rows and adding to list
    if (cursor.moveToFirst()) {
        do {
            Case c = new Case();

            long millis = cursor.getLong(cursor.getColumnIndexOrThrow("DATENOW"));
            Date addedOn = new Date(millis);
            c.setCaseNumber(cursor.getString(0));
            c.setDate(addedOn.toLocaleString());
            c.setStatus(cursor.getString(cursor.getColumnIndex(STATUS)));
            caseList.add(c);
        } while (cursor.moveToNext());
    }
    cursor.close();
    db.close();
    return caseList;
}

此方法将构造Case对象,并将其添加到ArrayList. 这个 ArrayList 将被返回。是的,我想你理解代码。但是6秒,真的吗?我究竟做错了什么?如何加快此操作?

谢谢!

4

1 回答 1

1

这取决于您的数据库结构(例如,如果 TABLE_CASES 只是另一个复杂查询)和 中的字段数TABLE_CASES,但至少以下几点可能会得到改进:

  • strftime('%s', DATE) * 1000)- 你真的每次需要CASE的时候都需要计算吗?存储该值而不是计算肯定会加快查询速度;
  • 不确定是否需要 ArrayList,可能CursorLoader可以使用;
  • 基于这个提示,调用new Date(millis)可能应该移出循环;
  • 对 and 的调用getColumnIndexOrThrowgetColumnIndex应该移出循环;
  • toLocaleString在 API 级别 1 中已弃用,请使用DateFormat

最后,我建议遵循这个 traceview 指南,并确定延迟是实际发生在 SQLite 中还是在它之后的循环中。

于 2012-11-20T13:20:54.007 回答