Wrote Loader for List of Alarms
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
package com.philliphsu.clock2.model;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.philliphsu.clock2.Alarm;
|
||||
import com.philliphsu.clock2.model.AlarmDatabaseHelper.AlarmCursor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Phillip Hsu on 7/2/2016.
|
||||
*/
|
||||
public class AlarmListLoader extends DataListLoader<Alarm, AlarmCursor> {
|
||||
|
||||
public AlarmListLoader(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
// Why not just have one method where we just call DatabaseManager.getAlarms()?
|
||||
// I.e. why not load the cursor and extract the Alarms from it all in one?
|
||||
// I figure if the loader is interrupted in the middle of loading, the underlying
|
||||
// cursor won't be closed...
|
||||
|
||||
// TODO: If we end up doing it this way, then delete the redundant methods in DatabaseManager.
|
||||
|
||||
@Override
|
||||
protected AlarmCursor loadCursor() {
|
||||
return DatabaseManager.getInstance(getContext()).queryAlarms();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Alarm> loadItems(AlarmCursor cursor) {
|
||||
ArrayList<Alarm> alarms = new ArrayList<>();
|
||||
if (cursor != null) {
|
||||
while (cursor.moveToNext()) {
|
||||
alarms.add(cursor.getAlarm());
|
||||
}
|
||||
cursor.close();
|
||||
}
|
||||
return alarms;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package com.philliphsu.clock2.model;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.CursorWrapper;
|
||||
import android.support.v4.content.AsyncTaskLoader;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Phillip Hsu on 7/2/2016.
|
||||
*/
|
||||
// TODO: Consider C extends MyTypeBoundedCursorWrapper<D>
|
||||
public abstract class DataListLoader<D, C extends CursorWrapper> extends AsyncTaskLoader<List<D>> {
|
||||
|
||||
private C mCursor;
|
||||
private List<D> mItems;
|
||||
|
||||
public DataListLoader(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
protected abstract C loadCursor();
|
||||
protected abstract List<D> loadItems(C cursor);
|
||||
|
||||
@Override
|
||||
public List<D> loadInBackground() {
|
||||
mCursor = loadCursor();
|
||||
if (mCursor != null) {
|
||||
// Ensure that the content window is filled
|
||||
// Ensure that the data is available in memory once it is
|
||||
// passed to the main thread
|
||||
mCursor.getCount();
|
||||
}
|
||||
return loadItems(mCursor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deliverResult(List<D> items) {
|
||||
if (isReset()) {
|
||||
// An async query came in while the loader is stopped
|
||||
if (mCursor != null) {
|
||||
mCursor.close();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
mItems = items;
|
||||
if (isStarted()) {
|
||||
super.deliverResult(items);
|
||||
}
|
||||
|
||||
// TODO: might not be necessary. The analogue of this was
|
||||
// to close the *old* cursor after assigning the new cursor.
|
||||
// This is closing the current cursor? But then again, we don't
|
||||
// care about the cursor after we've extracted the items from it..
|
||||
// Close the cursor because it is no longer needed.
|
||||
if (mCursor != null && !mCursor.isClosed()) {
|
||||
mCursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStartLoading() {
|
||||
if (mCursor != null && mItems != null) {
|
||||
// Deliver any previously loaded data immediately.
|
||||
deliverResult(mItems);
|
||||
}
|
||||
if (takeContentChanged() || mCursor == null || mItems == null) {
|
||||
forceLoad();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStopLoading() {
|
||||
// Attempt to cancel the current load task if possible.
|
||||
cancelLoad();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCanceled(List<D> data) {
|
||||
if (mCursor != null && !mCursor.isClosed()) {
|
||||
mCursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onReset() {
|
||||
super.onReset();
|
||||
// Ensure the loader is stopped
|
||||
onStopLoading();
|
||||
if (mCursor != null && !mCursor.isClosed()) {
|
||||
mCursor.close();
|
||||
}
|
||||
mCursor = null;
|
||||
mItems = null;
|
||||
}
|
||||
}
|
||||
@@ -63,10 +63,20 @@ public class DatabaseManager {
|
||||
}
|
||||
|
||||
/** @deprecated Use {@link #queryAlarms()} */
|
||||
// TODO: Possible redundant. See AlarmListLoader.
|
||||
@Deprecated
|
||||
public ArrayList<Alarm> getAlarms() {
|
||||
return getAlarms(mHelper.queryAlarms());
|
||||
}
|
||||
|
||||
// TODO: Possible redundant. See AlarmListLoader.
|
||||
public ArrayList<Alarm> getEnabledAlarms() {
|
||||
return getAlarms(mHelper.queryEnabledAlarms());
|
||||
}
|
||||
|
||||
// TODO: Possible redundant. See AlarmListLoader.
|
||||
private ArrayList<Alarm> getAlarms(AlarmCursor cursor) {
|
||||
ArrayList<Alarm> alarms = new ArrayList<>();
|
||||
AlarmCursor cursor = mHelper.queryAlarms();
|
||||
if (cursor != null) {
|
||||
while (cursor.moveToNext()) {
|
||||
alarms.add(cursor.getAlarm());
|
||||
|
||||
@@ -10,6 +10,8 @@ import android.support.v4.content.AsyncTaskLoader;
|
||||
* Efficiently loads and holds a Cursor.
|
||||
*/
|
||||
public abstract class SQLiteCursorLoader extends AsyncTaskLoader<Cursor> {
|
||||
private static final String TAG = "SQLiteCursorLoader";
|
||||
|
||||
private Cursor mCursor;
|
||||
|
||||
public SQLiteCursorLoader(Context context) {
|
||||
@@ -18,6 +20,7 @@ public abstract class SQLiteCursorLoader extends AsyncTaskLoader<Cursor> {
|
||||
|
||||
protected abstract Cursor loadCursor();
|
||||
|
||||
/* Runs on a worker thread */
|
||||
@Override
|
||||
public Cursor loadInBackground() {
|
||||
Cursor cursor = loadCursor();
|
||||
@@ -30,20 +33,28 @@ public abstract class SQLiteCursorLoader extends AsyncTaskLoader<Cursor> {
|
||||
return cursor;
|
||||
}
|
||||
|
||||
/* Runs on the UI thread */
|
||||
@Override
|
||||
public void deliverResult(Cursor data) {
|
||||
public void deliverResult(Cursor cursor) {
|
||||
if (isReset()) {
|
||||
// An async query came in while the loader is stopped
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
return;
|
||||
}
|
||||
Cursor oldCursor = mCursor;
|
||||
mCursor = data;
|
||||
mCursor = cursor;
|
||||
|
||||
if (isStarted()) {
|
||||
super.deliverResult(data);
|
||||
super.deliverResult(cursor);
|
||||
}
|
||||
|
||||
// Close the old cursor because it is no longer needed.
|
||||
// Because an existing cursor may be cached and redelivered, it is important
|
||||
// to make sure that the old cursor and the new cursor are not the
|
||||
// same before the old cursor is closed.
|
||||
if (oldCursor != null && oldCursor != data && !oldCursor.isClosed()) {
|
||||
if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed()) {
|
||||
oldCursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user