Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package org.gawst.asyncdb;
  
  import  android.annotation.SuppressLint;
  import  android.content.ContentValues;
  import  android.database.sqlite.SQLiteDatabaseCorruptException;
  import  android.os.Handler;
  import  android.os.HandlerThread;
  import  android.os.Message;
  import  android.support.annotation.NonNull;
 import  android.support.annotation.Nullable;
 import  android.util.Pair;
 
 
the main helper class that saves/restore item in memory using a DB storage

the storage handling is done in a separate thread

Parameters:
<E> the type of items stored in memory
Author(s):
Steve Lhomme
See also:
AsyncDbHelperHandler
org.gawst.asyncdb.AsynchronousDatabase
 
 public abstract class AsynchronousDbHelper<E, INSERT_ID> implements DataSource.BatchReadingCallback<E> {
 
 	public final static String TAG = "MemoryDb";
 	protected final static String STARTUP_TAG = "Startup";
 	protected final static boolean DEBUG_DB = false;
 
 	private static final int MSG_LOAD_IN_MEMORY    = 100;
 	private static final int MSG_STORE_ITEM        = 101;
 	private static final int MSG_STORE_ITEMS       = 102;
 	private static final int MSG_REMOVE_ITEM       = 103;
 	private static final int MSG_UPDATE_ITEM       = 104;
 	private static final int MSG_CLEAR_DATABASE    = 105;
 	private static final int MSG_SWAP_ITEMS        = 106;
 	private static final int MSG_REPLACE_ITEM      = 107;
 	private static final int MSG_CUSTOM_OPERATION  = 108;
 
 	private static final UIHandler UI_HANDLER = new UIHandler();
 
 	private WeakReference<AsynchronousDbErrorHandler<E>> mErrorHandler// not protected for now
 
 	private final AtomicBoolean mDataLoaded = new AtomicBoolean();
 	final DataSource<E, INSERT_ID> dataSource;
 	private final String name;
 
 
 	private final static HandlerThread handlerThread = new HandlerThread("AsynchronousDbHelper", android.os.Process.THREAD_PRIORITY_BACKGROUND);
 	static {
 		.start();
 	}

A class similar to AsyncQueryHandler to do simple calls asynchronously with a callback when it's done. Only works with AsynchronousDbHelper classes that use a DatabaseSource source.

You can create your own with custom callback handling with org.gawst.asyncdb.AsyncDbHelperHandler.

 
 	public class AsyncHandler extends AsyncDbHelperHandler<INSERT_ID> {
 		public AsyncHandler() {
 			super(AsynchronousDbHelper.this);
 		}
 	}

Parameters:
db The already created android.database.sqlite.SQLiteOpenHelper to use as storage
name Database name for logs
logger The org.gawst.asyncdb.Logger to use for all logs (can be null for the default Android logs)
initCookie Cookie to pass to preloadInit(Object)
 
 	@SuppressLint("HandlerLeak")
 	protected AsynchronousDbHelper(DataSource<E, INSERT_ID> dbfinal String nameLogger loggerObject initCookie) {
 		this. = db;
 		this. = name;
 
 		if (logger!=null)
 			LogManager.setLogger(logger);
 
 		preloadInit(initCookie);
 
 	}
 
 	private final Handler saveStoreHandler = new Handler(.getLooper()) {
 		public void handleMessage(Message msg) {
 			switch (msg.what) {
					break;
					break;
					@SuppressWarnings("unchecked")
					Pair<E, PurgeHandleritemToAdd = (Pair<E, PurgeHandler>) msg.obj;
					storeItem(itemToAdd.first, itemToAdd.second);
					break;
					@SuppressWarnings("unchecked")
					Pair<Collection<? extends E>, PurgeHandleritemsToAdd = (Pair<Collection<? extends E>, PurgeHandler>) msg.obj;
					storeItems(itemsToAdd.first, itemsToAdd.second);
					break;
					@SuppressWarnings("unchecked")
itemToDelete = (E) msg.obj;
					removeItem(itemToDelete);
					break;
					@SuppressWarnings("unchecked")
itemToUpdate = (E) msg.obj;
					updateItem(itemToUpdate);
					break;
					@SuppressWarnings("unchecked")
					Pair<E, E> itemsToReplace = (Pair<E, E>) msg.obj;
					replaceItem(itemsToReplace.first, itemsToReplace.second);
					break;
					@SuppressWarnings("unchecked")
					Pair<E, E> itemsToSwap = (Pair<E, E>) msg.obj;
					swapItems(itemsToSwap.first, itemsToSwap.second);
					break;
					try {
						@SuppressWarnings("unchecked")
catch (Exception e) {
						..w( + " failed to run operation " + msg.obj, e);
					}
					break;
			}
			super.handleMessage(msg);
		}
	};
	private void loadInMemory() {
		try {
				try {
catch (Exception e) {
					..w("Can't query source " +  + " in " + e);
				}
			}
catch (Exception e) {
			if (e instanceof SQLiteDatabaseCorruptException || e.getCause() instanceof SQLiteDatabaseCorruptException)
			else
				..w("Can't open database " + e);
finally {
		}
	}
	private void clearAllData() {
		try {
catch (Throwable e) {
			..w("Failed to empty table " +  + " in " + e);
finally {
			.sendEmptyMessage(); // reload the DB into memory
		}
	}
	private void storeItem(@NonNull E item, @Nullable PurgeHandler purgeHandler) {
		ContentValues addValues = null;
		boolean itemAdded = false;
		try {
			addValues = getValuesFromData(itemfalse);
			if (addValues != null) {
				directStoreItem(addValues);
				itemAdded = true;
			}
catch (Exception e) {
			notifyAddItemFailed(itemaddValuese);
finally {
			if (itemAdded) {
				if (purgeHandler != null) {
				}
				if (!notifyOnSchedule()) {
				}
			}
		}
	}
	private void storeItems(@NonNull Collection<? extends E> items, @Nullable PurgeHandler purgeHandler) {
		ContentValues addValues;
		boolean itemsAdded = false;
		for (E item : items) {
			addValues = null;
			try {
				addValues = getValuesFromData(itemfalse);
				if (addValues != null) {
					directStoreItem(addValues);
					itemsAdded = true;
				}
catch (Exception e) {
				notifyAddItemFailed(itemaddValuese);
			}
		}
		if (itemsAdded) {
			if (purgeHandler != null) {
			}
			if (!notifyOnSchedule()) {
			}
		}
	}
	private void removeItem(@NonNull E itemToDelete) {
		try {
			if (..d( + " remove " + itemToDelete);
			if (!.delete(itemToDelete)) {
				notifyRemoveItemFailed(itemToDeletenew RuntimeException("No item " + itemToDelete + " in " + ));
else if (!notifyOnSchedule()) {
			}
catch (Throwable e) {
			notifyRemoveItemFailed(itemToDeletee);
		}
	}
	private void updateItem(@NonNull E itemToUpdate) {
		ContentValues updateValues = null;
		try {
			updateValues = getValuesFromData(itemToUpdatetrue);
			if (!directUpdate(itemToUpdateupdateValues)) {
				notifyUpdateItemFailed(itemToUpdateupdateValuesnew RuntimeException("Can't update " + updateValues + " in " + ));
else if (!notifyOnSchedule()) {
			}
catch (Throwable e) {
			notifyUpdateItemFailed(itemToUpdateupdateValuese);
		}
	}
	private void replaceItem(@NonNull E src, @NonNull E replacement) {
		try {
			ContentValues replacementValues = getValuesFromData(srctrue);
			if (directUpdate(replacementreplacementValues)) {
				if (!notifyOnSchedule()) {
				}
			}
catch (Throwable e) {
			notifyReplaceItemFailed(srcreplacemente);
		}
	}
	private void swapItems(@NonNull E first, @NonNull E second) {
		ContentValues newValuesA = null;
		try {
			newValuesA = getValuesFromData(secondtrue);
			if (newValuesA != null) {
				if (..d( + " update " + second + " with " + newValuesA);
				directUpdate(firstnewValuesA);
			}
catch (Throwable e) {
			notifyUpdateItemFailed(firstnewValuesAe);
		}
		ContentValues newValuesB = null;
		try {
			newValuesB = getValuesFromData(firsttrue);
			if (newValuesB != null) {
				if (..d( + " update " + first + " with " + newValuesB);
				directUpdate(secondnewValuesB);
			}
catch (Throwable e) {
			notifyUpdateItemFailed(secondnewValuesBe);
		}
		if (!notifyOnSchedule()) {
		}
	}

Method to call to insert data directly in the database

Parameters:
addValues Values that will be written in the database
Throws:
RuntimeException if the insertion failed
	private void directStoreItem(ContentValues addValuesthrows RuntimeException {
		INSERT_ID inserted = .insert(addValues);
		if (..d(AsynchronousDbHelper.this+" insert "+addValues+" = "+inserted);
		if (inserted==nullthrow new RuntimeException("failed to add values "+addValues+" in ");
	}

Method to call to update the data directly in the database

Parameters:
itemToUpdate Item in the database that needs to be updated
updateValues Values that will be updated in the database
Returns:
true if the data were updated successfully
	protected final boolean directUpdate(E itemToUpdate, ContentValues updateValues) {
		if (updateValues!=null) {
			if (..d(AsynchronousDbHelper.this+" update "+updateValues+" for "+itemToUpdate);
			return .update(itemToUpdateupdateValues/*, SQLiteDatabase.CONFLICT_NONE*/);
		}
		return false;
	}

Method called at the end of constructor, just before the data start loading

Parameters:
cookie Data that may be needed to initialize all internal storage
	protected void preloadInit(Object cookie) {
	}

tell the InMemory database that we are about to modify its data

see also popModifyingTransaction()

	protected void pushModifyingTransaction() {
	}
	private final Runnable dataChanged = new Runnable() {
		public void run() {
				final InMemoryDbListener<E> listener = l.get();
				if (listener==null)
				else
			}
		}
	};

tell the InMemory database we have finish modifying the data at this level. Once the pop matches all the pushes org.gawst.asyncdb.InMemoryDbListener.onMemoryDbChanged(AsynchronousDbHelper) is called

this is useful to avoid multiple calls to org.gawst.asyncdb.InMemoryDbListener.onMemoryDbChanged(AsynchronousDbHelper) during a batch of changes

see also pushModifyingTransaction()

	protected void popModifyingTransaction() {
		}
	}

Returns:
true if all org.gawst.asyncdb.InMemoryDbListener.onMemoryDbChanged(AsynchronousDbHelper) should be called right after a schedule call or after the call is processed.
See also:
scheduleAddOperation(Object)
scheduleAddOperation(Object, org.gawst.asyncdb.purge.PurgeHandler)
scheduleAddOperation(java.util.Collection)
scheduleAddOperation(java.util.Collection, org.gawst.asyncdb.purge.PurgeHandler)
scheduleRemoveOperation(Object)
scheduleUpdateOperation(Object)
scheduleReplaceOperation(Object, Object)
scheduleSwapOperation(Object, Object)
	protected boolean notifyOnSchedule() {
		return true;
	}
	protected void clearDataInMemory() {}

set the listener that will receive error events

Parameters:
listener null to remove the listener
	protected void setDbErrorHandler(AsynchronousDbErrorHandler<E> listener) {
		if (listener==null)
			 = null;
		else
	}
		return ;
	}
	public void setPurgeHandler(PurgeHandler purgeHandler) {
		this. = purgeHandler;
	}

Call this after an element is inserted for the purge to do its job.
	public void triggerPurgeHandler() {
		if (null != ) {
		}
	}
	public void addListener(final InMemoryDbListener<E> listener) {
			if (l.get()==null)
			else if (l.get()==listener)
				return;
		}
				public void run() {
				}
			});
	}
	public void removeListener(InMemoryDbListener<E> listener) {
			if (l.get()==null)
			else if (l.get()==listener)
		}
	}

Delete all the data in memory (synchronous) and in the database (asynchronous).
	public final void clear() {
	}
	private void notifyAddItemFailed(E item, ContentValues valuesThrowable cause) {
		..d(this+" failed to add item "+item+( ? (" values"+values) : ""), cause);
		if (!=null) {
			final AsynchronousDbErrorHandler<E> listener = .get();
			if (listener==null)
				 = null;
			else
				listener.onAddItemFailed(thisitemvaluescause);
		}
	}
	private void notifyReplaceItemFailed(E srcItem, E replacementThrowable cause) {
		..i(this+" failed to replace item "+srcItem+" with "+replacementcause);
		if (!=null) {
			final AsynchronousDbErrorHandler<E> listener = .get();
			if (listener==null)
				 = null;
			else
				listener.onReplaceItemFailed(thissrcItemreplacementcause);
		}
	}
	private void notifyUpdateItemFailed(E item, ContentValues valuesThrowable cause) {
		..i(this+" failed to update item "+item+( ? (" values"+values) : ""), cause);
		if (!=null) {
			final AsynchronousDbErrorHandler<E> listener = .get();
			if (listener==null)
				 = null;
			else
				listener.onAddItemFailed(thisitemvaluescause);
		}
	}
	private void notifyRemoveItemFailed(E itemThrowable cause) {
		..i(this+" failed to remove item "+itemcause);
		if (!=null) {
			final AsynchronousDbErrorHandler<E> listener = .get();
			if (listener==null)
				 = null;
			else
				listener.onRemoveItemFailed(thisitemcause);
		}
	}
	private void notifyDatabaseCorrupted(DataSource<E, INSERT_ID> dataSourceString nameThrowable cause) {
		..e("table "this. +" is corrupted in "+name);
		if (!=null) {
			final AsynchronousDbErrorHandler<E> listener = .get();
			if (listener==null)
				 = null;
			else
				listener.onCorruption(this);
		}
		dataSource.eraseSource();
	}

Transform the element in memory into android.content.ContentValues that can be saved in the database.

you can return null and fill the database yourself if you need to.

Parameters:
data the data to transform
update true if the values are for an update, not an insert, you can omit keys there.
Returns:
a ContentValues element with all data that can be used to restore the data later from the database.
See also:
addItemInMemory(Object)
	@Nullable
	protected abstract ContentValues getValuesFromData(E databoolean updatethrows RuntimeException;

Request to store the item in the database asynchronously

Will call the org.gawst.asyncdb.AsynchronousDbErrorHandler.onAddItemFailed(AsynchronousDbHelper, Object, android.content.ContentValues, Throwable) on failure

Parameters:
item to add
	protected final void scheduleAddOperation(E item) {
	}

Request to store the item in the database asynchronously

Will call the AsynchronousDbErrorHandler.onAddItemFailed() on failure

Parameters:
item to add
purgeHandler
	protected final void scheduleAddOperation(E itemPurgeHandler purgeHandler) {
		if (null != item) {
			.sendMessage(Message.obtain(new Pair<E, PurgeHandler>(itempurgeHandler)));
			}
		}
	}

Request to store the items in the database asynchronously

Will call AsynchronousDbErrorHandler.onAddItemFailed() on each item failing

Parameters:
items to add
	protected final void scheduleAddOperation(Collection<? extends E> items) {
	}

Request to store the items in the database asynchronously

Will call AsynchronousDbErrorHandler.onAddItemFailed() on each item failing

Parameters:
items to add
purgeHandler
	protected final void scheduleAddOperation(Collection<? extends E> itemsPurgeHandler purgeHandler) {
		if (null != items) {
			.sendMessage(Message.obtain(new Pair<Collection<? extends E>, PurgeHandler>(itemspurgeHandler)));
			}
		}
	}

Request to update the item in the database asynchronously

org.gawst.asyncdb.source.DatabaseElementHandler.getItemSelectClause(Object) is used to find the matching item in the database

Will call AsynchronousDbErrorHandler.onUpdateItemFailed() on failure

Parameters:
item to update
See also:
getValuesFromData(Object, boolean)
	protected final void scheduleUpdateOperation(@NonNull E item) {
		if (null != item) {
			.sendMessage(Message.obtain(item));
			}
		}
	}

Request to replace an item in the databse with another asynchronously

org.gawst.asyncdb.source.DatabaseElementHandler.getItemSelectClause(Object) is used to find the matching item in the database

Will call AsynchronousDbErrorHandler.onReplaceItemFailed() on failure

Parameters:
original Item to replace
replacement Item to replace with
	protected final void scheduleReplaceOperation(@NonNull E original, @NonNull E replacement) {
		.sendMessage(Message.obtain(new Pair<E, E>(originalreplacement)));
		}
	}
	protected final void scheduleSwapOperation(@NonNull E itemA, @NonNull E itemB) {
		.sendMessage(Message.obtain(new Pair<E,E>(itemAitemB)));
		}
	}

Request to delete the item from the database

Will call the AsynchronousDbErrorHandler.onRemoveItemFailed() on failure

Parameters:
item to remove
	protected final void scheduleRemoveOperation(E item) {
		if (null != item) {
			.sendMessage(Message.obtain(item));
			}
		}
	}

run the operation in the internal thread

Parameters:
operation
	public final void scheduleCustomOperation(@NonNull AsynchronousDbOperation operation) {
		.sendMessage(Message.obtain(operation));
	}

called when we are about to read all items from the disk
	protected void startLoadingInMemory() {
	}
	public void startLoadingAllItems(int elementCount) {}

called after all items have been read from the disk
	protected void finishLoadingInMemory() {
	}
	public void removeInvalidEntry(final InvalidEntry invalidEntry) {
			public void runInMemoryDbOperation(AsynchronousDbHelper<?, ?> db) {
				// remove the element from the DB forever
			}
		});
	}

Tell whether the database loading should be done or not

If you don't store the elements in memory, you don't need to load the whole data

	protected boolean shouldReloadAllData() {
		return true;
	}
	public boolean isDataLoaded() {
		return .get();
	}

Wait until the data are loaded
	public void waitForDataLoaded() {
	}
	public String toString() {
		StringBuilder sb = new StringBuilder(48);
		sb.append("{AsyncDB:");
		sb.append(' ');
		sb.append(Integer.toHexString(System.identityHashCode(this)));
		sb.append('}');
		return sb.toString();
	}
New to GrepCode? Check out our FAQ X