Вопрос

I am starting a new Android project and would like to know all about OrmLite + keeping database access off the UI Thread.

OLD: In my last project, I used a ThreadPoolExecutor and a new AsyncTask object for every insert/update/delete call, so that those calls would be executed off the UI thread. I did the select request on the UI thread, just to keep it simple.

NEW: In my new app I want to do all the db calls off the UI thread.

Is using a ThreadPoolExecutors in my Controller classes still the way to go? (I use a seperate controller class for every model object, that calls the DAO methods for this object and handles the callbacks). What are the best/new options? Creating ONE service with ONE background thread that handles database access?

Any links to best practise guides on Android + Ormlite + off the uid thread would be appreciated.

Это было полезно?

Решение

I recommend to use the LoaderManager to query data from the database in the background.

The most simple query in a loader would be that:

public class CustomLoader extends AsyncTaskLoader<List<? extends DbBase>> {
    private static final String LOG_TAG = CustomLoader.class.getSimpleName();

    // DbBase is the parent class of all ORMLite data objects.
    private List<? extends DbBase> mData;

    public CustomLoader(Context context) {
        super(context);
    }

    @Override
    public List<? extends DbBase> loadInBackground() {
        return DatabaseAdapter.getInstance().getORMLiteObjectDao().queryForAll();
    }

    @Override
    public void deliverResult(List<? extends DbBase> data) {
        if (isReset()) {
            return;
        }

        mData = data;

        if (isStarted()) {
            super.deliverResult(data);
        }
    }

    @Override
    protected void onStartLoading() {
        if (mData != null) {
            deliverResult(mData);
        }

        if (takeContentChanged() || mData == null) {
            forceLoad();
        }
    }

    @Override
    protected void onStopLoading() {
        cancelLoad();
    }

    @Override
    protected void onReset() {
        // Ensure the loader has been stopped.
        onStopLoading();

        // At this point we can release the resources associated with 'mData'.
        if (mData != null) {
            mData = null;
        }
    }
}

As I did quite some heavy transactions (update/delete/inserts) I used an ExecutorService, created a chached ThreadPool and executed the transaction within the executor:

final Callable<SyncResult> transactionCall = new Callable<SyncResult>() {
    @Override
    public SyncResult call() throws Exception {
        // do the sql magic
    }
};

MyApplication.execute(new Runnable() {
    @Override
    public void run() {
        try {
            TransactionManager.callInTransaction(DatabaseAdapter.getInstance().getConnectionSource(), transactionCall);
        } catch (SQLException e) {
            Log.e(LOG_TAG, "Error in DB transaction", e);
        }
    }
});

As long transactions will result in a locked database, I recommend to enable "write ahead" (requires API 11!).

SQLiteDatabase db = mHelper.getWritableDatabase();
if (db != null && db.enableWriteAheadLogging()) { // requires API 11!
    Log.d(LOG_TAG, "Write ahead enabled!");
    mHelper.getRuntimeExceptionDao(ORMliteDataClass.class).queryRaw("PRAGMA journal_mode = \"WAL\"");
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top