How to make a SELECT from MySQLite without locking the UI?

Viewed 59

I have an issue with my Activity, that's an old Android project which I'm trying to refactor a bit to increase the performance of the App.

In onCreate I'm doing a SELECT of data from different tables like this:

@Override
protected void onCreate(Bundle savedInstanceState) {
    LoadDataDB();
}

And LoadDataDB looks like this:

public void LoadDataDB() {
    myDB = DataBaseHandler.getInstance(this);

    menuConstructors = myDB.getMenu();
    items = myDB.getTasti();
    variantiConstructors = myDB.getVarianti();
    printers = myDB.getPrinters();

    if (myDB.getFamiglie().size() != 0) {
        myDB.deleteFam();
    }
    for (VariantiConstructor variantiConstructor : variantiConstructors) {
        if (!variantiConstructor.getFamiglie().equals("") && !variantiConstructor.getFamiglie().equals("0")) {
            myDB.insertFamiglie(variantiConstructor.getFamiglie());
        }
    }

    modelFamiglie = myDB.getFamiglie();

}

Then each function like getMenu is built as the following:

public ArrayList<MenuConstructor> getMenu() {
    database = this.getReadableDatabase();
    Cursor cursor = database.query(TABLE_MENU, null, null, null, null, null, null);
    ArrayList<MenuConstructor> contacts = new ArrayList<>();
    MenuConstructor contactModel;
    if (cursor.getCount() > 0) {
        for (int i = 0; i < cursor.getCount(); i++) {
            cursor.moveToNext();
            contactModel = new MenuConstructor(Integer.parseInt(cursor.getString(0)),
                    cursor.getString(1),cursor.getString(2),
                    cursor.getString(3));
            contacts.add(contactModel);
        }
    }
    cursor.close();
    database.close();
    return contacts;
}

When I open the activity it's locked at the SplashScreen until the data is fetched, so how could I refactor that functions to make them something like async which wouldn't lock the UI?

1 Answers

To prevent locking the UI you need to perform your SELECT queries on another thread. If you would use Kotlin I would recommend coroutines.

I started to use ThreadPoolExecutor for this task.

You could create a static instance of ThreadPoolExecutor inside your DatabaseHandler like this:

public static final ExecutorService databaseWriteExecutor =  Executors.newFixedThreadPool(NUMBER_OF_THREADS);

and use this instance to execute your queries.

To execute instructions on another thread you can use:

DatabaseHandler.databaseWriteExecutor.execute(new Runnable() {
        @Override
        public void run() {
            LoadDataDB();
        }
    });

After this you just need to solve one small issue. You need to perform your UI changes on the UI Thread. There is more than one solution for this issue.

One solution would be to create a Handler of the UI Thread Looper and post your UI changes like this.

Another solution would be to create LiveData instances and observe the data changes (Observer Callbacks are always on the UI Thread)

Related