From 9686d9d07e344fae2f2310ca544e5401b5e11d30 Mon Sep 17 00:00:00 2001 From: John Reck Date: Wed, 16 Jan 2013 14:10:30 -0800 Subject: New loading model Rename reload() to loadIfDirty() loadIfDirty is implemented by MediaSet and is final loadIfDirty is now blocking instead of async Subclasses must implement two protected methods, isDirtyLocked() and load() The change from async reload() to sync loadIfDirty() should be fine since all users of reload() were doing so from a background thread already, and the longest load() is PicasaAlbumSet which is still a fairly brisk 40ms or so Change-Id: If5cc596a1c13e52e5f4efff1a144bd086d37cfb7 --- src/com/android/gallery3d/data/MediaSet.java | 87 +++++++++++++++++++++++----- 1 file changed, 72 insertions(+), 15 deletions(-) (limited to 'src/com/android/gallery3d/data/MediaSet.java') diff --git a/src/com/android/gallery3d/data/MediaSet.java b/src/com/android/gallery3d/data/MediaSet.java index 9bc148f89..cc8a4a71a 100644 --- a/src/com/android/gallery3d/data/MediaSet.java +++ b/src/com/android/gallery3d/data/MediaSet.java @@ -18,6 +18,8 @@ package com.android.gallery3d.data; import com.android.gallery3d.common.Utils; import com.android.gallery3d.util.Future; +import com.android.gallery3d.util.ThreadPool.CancelListener; +import com.android.gallery3d.util.ThreadPool.JobContext; import java.util.ArrayList; import java.util.WeakHashMap; @@ -54,6 +56,9 @@ public abstract class MediaSet extends MediaObject { void onSyncDone(MediaSet mediaSet, int resultCode); } + private Object mLoadLock = new Object(); + private boolean mIsLoading; + public MediaSet(Path path, long version) { super(path, version); } @@ -99,14 +104,6 @@ public abstract class MediaSet extends MediaObject { return false; } - /** - * Method {@link #reload()} may process the loading task in background, this method tells - * its client whether the loading is still in process or not. - */ - public boolean isLoading() { - return false; - } - public int getTotalMediaItemCount() { int total = getMediaItemCount(); for (int i = 0, n = getSubMediaSetCount(); i < n; i++) { @@ -176,15 +173,76 @@ public abstract class MediaSet extends MediaObject { } } - // Reload the content. Return the current data version. reload() should be called - // in the same thread as getMediaItem(int, int) and getSubMediaSet(int). - public abstract long reload(); + // TODO: Remove this once createJobContextCompat is no longer needed + // Note that canceling a load is not strictly supported as it can leave + // MediaSets with bad internal state. Fortunately they are never canceled + // anywhere, so the isCancelled() exists purely for completeness sake + private static class LoadJobContextCompat implements JobContext { + + @Override + public boolean isCancelled() { + return Thread.interrupted(); + } + + @Override + public void setCancelListener(CancelListener listener) { + } + + @Override + public boolean setMode(int mode) { + return false; + } + } + + @Deprecated + protected final JobContext createJobContextCompat() { + return new LoadJobContextCompat(); + } + + /** + * Synchronously load if the MediaSet is dirty. Note that this must be called + * on the same thread as getMediaItem(int, int) and getSubMediaSet(int) + * @return DataVersion + */ + public final long loadIfDirty() { + try { + boolean doLoad = false; + synchronized (mLoadLock) { + if (mIsLoading) { + mLoadLock.wait(); + } + doLoad = isDirtyLocked(); + if (doLoad) { + mIsLoading = true; + } + } + if (doLoad) { + load(); + synchronized (mLoadLock) { + mDataVersion = nextVersionNumber(); + mIsLoading = false; + mLoadLock.notifyAll(); + } + } + } catch (InterruptedException ex) { + } + return getDataVersion(); + } + + /** + * Called inside of synchronized(mLoadLock). It is guaranteed this will only + * be called once before a call to load() if this returns true. It is + * acceptable to clear any internal dirty flags in this function as a result. + * @return true if the set wants a load() call, false otherwise + */ + protected abstract boolean isDirtyLocked(); /** - * Synchronously load if the MediaSet is dirty - * @return True if new data was loaded, false otherwise + * Synchronously load the MediaSet. Only called if {@link #isDirtyLocked()} + * returned true + * @throws InterruptedException if the load was interrupted */ - public boolean loadIfDirty() { throw new IllegalStateException("not implemented"); } + protected abstract void load() throws InterruptedException; @Override public MediaDetails getDetails() { @@ -283,7 +341,6 @@ public abstract class MediaSet extends MediaObject { } private class MultiSetSyncFuture implements Future, SyncListener { - @SuppressWarnings("hiding") private static final String TAG = "Gallery.MultiSetSync"; private final SyncListener mListener; -- cgit v1.2.3