Loaders and onLoaderReset Android
Asked Answered
B

1

11

I implemented a Loader in my application for querying data from the database. I listen the changes that happen' by implementing LoaderCallbacks<Cursor> listener. The problem that I have is when using the onLoaderReset(Loader<Cursor> loader) method when my data change and I want to invalidate and free any data associated with the loader. In all the examples, in this method there is the following call:

mAdapter.swapCursor(null);

But the thing is I don't use the data from the cursor in adapter, I use it in some other way in my application.

(directly from the returned cursor in onLoadFinished(Loader<Cursor> loader, Cursor data), for example)

        @Override
        public void onLoadFinished(Loader<Cursor> loader, Cursor data) {

            if (data.moveToFirst()) {
                TOTAL_CARDS = data.getCount();
                mView.createCards(TOTAL_CARDS);
            } else {
                TOTAL_CARDS = 0;
                mView.createCards(TOTAL_CARDS);
            }


        }

What would be the corresponding thing to do here, that is similar with mAdapter.swapCursor. I don't have much experience with loaders, in fact I just started working with them, so if someone has a solution to this, I would appreciate it. Thx!

EDIT: For now, I am passing null to the loader and it works, like this:

@Override
public void onLoaderReset(Loader<Cursor> loader) {
        loader = null;
}

};

But is this the right solution?

Bing answered 17/10, 2012 at 14:49 Comment(0)
M
27

Doing

@Override
public void onLoaderReset(Loader<Cursor> loader) {
  loader = null;
}

is just as good as doing nothing. In your example code, you are merely nulling your method's local reference to its argument. However, this reference will always be removed after the return of the method call. (You might want to read Is Java "pass-by-reference" or "pass-by-value"? for a further discussion of the topic.)

The onLoaderReset(Loader) method gets called when your loader's callback (usually an Activity or Fragment instance) is asked to release all references to the Cursor which it has gained via onLoadFinished(Loader, Cursor) before. Basically this method asks you to clean up since the Loader will soon close the Cursor it provided to you before. After the cursor was closed, you will not longer be able to retrieve data by it. If the cursor would however still be in use (typically by a CursorAdapter as you mentioned) after it was closed, this would cause an exception to be thrown.

Similarly, onLoadFinished(Loader, Cursor) has an implicit contract asking that after the method returns any formerly provided Cursor objects must not longer be in use. Instead, you have to replace these references by the new cursor which is provided as a method argument. In contrast, onLoaderReset(Loader) asks you to fulfill the same contract, but without providing a replacement, i.e. you should remove all references to a formerly retrieved Cursor.

In your example, you do not let your Cursor escape the method scope but instead you are reading the data right away. Therefore, it is not necessary to remove any references to a Cursor object which was provided via onLoadFinished(Loader, Cursor) since there are none. An empty implementation of onLoaderReset(Loader) to fulfill the interface contract will therefore do the job for you.

Martelli answered 2/5, 2013 at 11:52 Comment(4)
Thank u for your answer and explanation. Just a quick question though. If I had a reference to a Cursor in onLoadFinished (that I would use outside the method scope), than I should close it in onLoaderReset, right?Bing
Actually, no. The loader will close the Cursor reference for you. This is the main reason why you are supposed to release the references. You will most likely not able to use the old cursor after the onLoadFinished(Loader, Cursor) / onLoaderReset(Loader) methods return.Martelli
So what is a good use-case to implement onLoaderReset() method?Thenceforward
The method is a life-cycle hook. You normally use the method to change the state of the enclosing instance or the Loader instance.Martelli

© 2022 - 2024 — McMap. All rights reserved.