简体   繁体   中英

Return value from thread (runnable)

I'm working with Room to persist data, the new AAC for persisting data, and I work on an app where the Todo app provided in the Google's github repository serves as our blueprint.
I've been trying to get a value returned by a transaction performed on an entity. I used a global variable mCategories to retrieve and store the data returned but I keep on having a null object being returned.

Here's my code:

 public interface LoadDataListener<T>
{
    void onReadTransactionCompleted(T arg);
}

private void readTransaction(final LoadDataListener<List<Category>> loadDataListener, final boolean onlyClassic)
{
    Runnable readRunnable = new Runnable() {
        @Override
        public void run() {
            List<Category> categories;
            if (!onlyClassic)
                categories = mCategoryDAO.loadAllSellingCategories();
            else
                categories = mCategoryDAO.loadAllClassicCategories();

            LOGD(TAG, "Category size: "+ categories.size());
            // The log above reads a value > 0
            loadDataListener.onReadTransactionCompleted(categories);
        }
    };

    mAppExecutors.diskIO().execute(readRunnable);
}

private List<Category> getSanitizedAndPersistedCategories(boolean onlyClassic) {
    readTransaction(new LoadDataListener<List<Category>>() {
        @Override
        public void onReadTransactionCompleted(List<Category> arg) {
            mCategories = arg;
            LOGD(TAG, "sanitizeCategoriesList size before: " + mCategories);
            // The log above reads a value > 0

        }
    }, onlyClassic);

    LOGD(TAG, "sanitizeCategoriesList size after: " + mCategories);
    // The log above reads null
    return sanitizeCategoriesList(mCategories);
}

What am I missing here ??

That's because you have 2 threads here.
When you call readTransaction() and then mAppExecutors.diskIO().execute(readRunnable) , method readTransaction() returns immediately and calls LOGD(TAG, "sanitizeCategoriesList size after: " + mCategories); , which as expected prints null . In the meantime, asynchronously on second thread, run() is executed, invoking at the end onReadTransactionCompleted() and finally setting mCategories value.

So you can only rely on mCategories after onReadTransactionCompleted() was invoked.

If you are using mCategories for UI related stuff, you might wanna consider using AsyncTask and moving your code from run() to doInBackground() and code from onReadTransactionCompleted() to onPostExecute()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM