I have done some measurements regarding the IO on my SQLite database. It takes around 6 seconds to load some object from this database. I have a class which extends Asynctask, this class job is to load the last 10 entries in my database. This class is constructed this way:
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);
}
}
As you may see, the measurements is done just before I call the method 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));
This will give me about 6 seconds to load 10 cases from the database, as I mentioned earlier.
Now, over to the getAllCases method
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;
}
This method will construct Case objects, and add this to an ArrayList. This ArrayList will be return. Yeah, I guess you understand the code. But 6 seconds, really? What am I doing wrong? How can I speed up this operation?
Thanks!
It depends on Your database structure (e.g. if TABLE_CASES is just another complex query) and number of fields in
TABLE_CASES, but at least the following points might be improved:strftime('%s', DATE) * 1000)– do You really need to calculate it every time when You need to get CASE? Storing of that value instead of calculation will definitely speed up the query;new Date(millis)probably should be moved out of the loop;getColumnIndexOrThrowandgetColumnIndexshould be also moved out of the loop;toLocaleStringis deprecated in API level 1 please use DateFormatFinally, I would suggest to follow this guide for traceview and determine if the delay actually happens in SQLite or in the loop just after it.