Java tutorial
/* * Copyright (c) 2012 - 2014 Ngewi Fet <ngewif@gmail.com> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.gnucash.android.db; import android.content.Context; import android.database.Cursor; import android.support.v4.content.AsyncTaskLoader; /** * Abstract base class for asynchronously loads records from a database and manages the cursor. * In order to use this class, you must subclass it and implement the * {@link #loadInBackground()} method to load the particular records from the database. * Ideally, the database has {@link DatabaseAdapter} which is used for managing access to the * records from the database * @author Ngewi Fet <ngewif@gmail.com> * @see DatabaseAdapter */ public abstract class DatabaseCursorLoader extends AsyncTaskLoader<Cursor> { /** * Cursor which will hold the loaded data set. * The cursor will be returned from the {@link #loadInBackground()} method */ private Cursor mCursor = null; /** * {@link DatabaseAdapter} which will be used to load the records from the database */ protected DatabaseAdapter mDatabaseAdapter = null; /** * A content observer which monitors the cursor and provides notifications when * the dataset backing the cursor changes. You need to register the oberserver on * your cursor using {@link #registerContentObserver(Cursor)} */ protected final ForceLoadContentObserver mObserver; /** * Constructor * Initializes the content observer * @param context Application context */ public DatabaseCursorLoader(Context context) { super(context); mObserver = new ForceLoadContentObserver(); } /** * Asynchronously loads the results from the database. */ public abstract Cursor loadInBackground(); /** * Registers the content observer for the cursor. * @param cursor {@link Cursor} whose content is to be observed for changes */ protected void registerContentObserver(Cursor cursor) { cursor.registerContentObserver(mObserver); } @Override public void deliverResult(Cursor data) { if (isReset()) { if (data != null) { onReleaseResources(data); } return; } Cursor oldCursor = mCursor; mCursor = data; if (isStarted()) { super.deliverResult(data); } if (oldCursor != null && oldCursor != data && !oldCursor.isClosed()) { onReleaseResources(oldCursor); } } @Override protected void onStartLoading() { if (mCursor != null) { deliverResult(mCursor); } if (takeContentChanged() || mCursor == null) { // If the data has changed since the last time it was loaded // or is not currently available, start a load. forceLoad(); } } @Override protected void onStopLoading() { cancelLoad(); } @Override public void onCanceled(Cursor data) { super.onCanceled(data); onReleaseResources(data); } /** * Handles a request to completely reset the Loader. */ @Override protected void onReset() { super.onReset(); onStopLoading(); // At this point we can release the resources associated with 'mCursor' // if needed. if (mCursor != null && !mCursor.isClosed()) { onReleaseResources(mCursor); } mCursor = null; } /** * Helper function to take care of releasing resources associated * with an actively loaded data set. * @param c {@link Cursor} to be released */ protected void onReleaseResources(Cursor c) { if (c != null) c.close(); if (mDatabaseAdapter != null) { mDatabaseAdapter.close(); } } }