diff --git a/src/org/kreed/vanilla/LibraryActivity.java b/src/org/kreed/vanilla/LibraryActivity.java index f142b2a8..1a40cdc8 100644 --- a/src/org/kreed/vanilla/LibraryActivity.java +++ b/src/org/kreed/vanilla/LibraryActivity.java @@ -58,11 +58,6 @@ import android.widget.Toast; * The library activity where songs to play can be selected from the library. */ public class LibraryActivity extends PlaybackActivity implements AdapterView.OnItemClickListener, TextWatcher { - /** - * The number of tabs in the song selector. - */ - private static final int TAB_COUNT = 5; - private static final int ACTION_PLAY = 0; private static final int ACTION_ENQUEUE = 1; private static final int ACTION_LAST_USED = 2; @@ -101,7 +96,7 @@ public class LibraryActivity extends PlaybackActivity implements AdapterView.OnI @Override public void onChange(boolean selfChange) { - runQuery(mPlaylistAdapter); + requestRequery(mPlaylistAdapter); } }; @@ -174,9 +169,6 @@ public class LibraryActivity extends PlaybackActivity implements AdapterView.OnI if (state != null) mTextFilter.setText(state.getString("filter")); - - // query adapters - onMediaChange(); } @Override @@ -302,32 +294,37 @@ public class LibraryActivity extends PlaybackActivity implements AdapterView.OnI */ private int setLimiter(MediaAdapter.Limiter limiter) { + int tab; + if (limiter == null) { mAlbumAdapter.setLimiter(null); mSongAdapter.setLimiter(null); - return -1; + tab = -1; + } else { + switch (limiter.type) { + case MediaUtils.TYPE_ALBUM: + mSongAdapter.setLimiter(limiter); + requestRequery(mSongAdapter); + return 2; + case MediaUtils.TYPE_ARTIST: + mAlbumAdapter.setLimiter(limiter); + mSongAdapter.setLimiter(limiter); + tab = 1; + break; + case MediaUtils.TYPE_GENRE: + mSongAdapter.setLimiter(limiter); + mAlbumAdapter.setLimiter(null); + tab = 2; + break; + default: + throw new IllegalArgumentException("Unsupported limiter type: " + limiter.type); + } } - switch (limiter.type) { - case MediaUtils.TYPE_ALBUM: - // Clear the cursor so we don't have the old selection showing when - // we switch to that tab. - mSongAdapter.changeCursor(null); - mSongAdapter.setLimiter(limiter); - return 2; - case MediaUtils.TYPE_ARTIST: - mAlbumAdapter.changeCursor(null); - mAlbumAdapter.setLimiter(limiter); - mSongAdapter.setLimiter(limiter); - return 1; - case MediaUtils.TYPE_GENRE: - mSongAdapter.changeCursor(null); - mSongAdapter.setLimiter(limiter); - mAlbumAdapter.setLimiter(null); - return 2; - default: - throw new IllegalArgumentException("Unsupported limiter type: " + limiter.type); - } + requestRequery(mSongAdapter); + requestRequery(mAlbumAdapter); + + return tab; } public void onItemClick(AdapterView list, View view, int pos, long id) @@ -351,15 +348,10 @@ public class LibraryActivity extends PlaybackActivity implements AdapterView.OnI public void onTextChanged(CharSequence text, int start, int before, int count) { - MediaAdapter adapter = mCurrentAdapter; - if (adapter != null) { - String filter = text.toString(); - adapter.filter(filter); - - for (int i = TAB_COUNT; --i != -1; ) { - if (mAdapters[i] != adapter) - mAdapters[i].filter(filter); - } + String filter = text.toString(); + for (MediaAdapter adapter : mAdapters) { + adapter.setFilter(filter); + requestRequery(adapter); } } @@ -751,6 +743,23 @@ public class LibraryActivity extends PlaybackActivity implements AdapterView.OnI return true; } + /** + * Requery the given adapter. If it is the current adapter, requery + * immediately. Otherwise, mark the adapter as needing a requery and requery + * when its tab is selected. + */ + public void requestRequery(MediaAdapter adapter) + { + if (adapter == mCurrentAdapter) { + runQuery(adapter); + } else { + adapter.requestRequery(); + // Clear the data for non-visible adapters (so we don't show the old + // data briefly when we later switch to that adapter) + adapter.changeCursor(null); + } + } + /** * Schedule a query to be run for the given adapter on the worker thread. * @@ -765,8 +774,8 @@ public class LibraryActivity extends PlaybackActivity implements AdapterView.OnI @Override public void onMediaChange() { - for (int i = 0; i != TAB_COUNT; ++i) - runQuery(mAdapters[i]); + for (MediaAdapter adapter : mAdapters) + requestRequery(adapter); } private void setSearchBoxVisible(boolean visible) @@ -811,7 +820,10 @@ public class LibraryActivity extends PlaybackActivity implements AdapterView.OnI */ private void setCurrentTab(int i) { - mCurrentAdapter = mAdapters[i]; + MediaAdapter adapter = mAdapters[i]; + mCurrentAdapter = adapter; + if (adapter.isRequeryNeeded()) + runQuery(adapter); mTabWidget.setCurrentTab(i); mLists.getChildAt(mCurrentTab).setVisibility(View.GONE); mLists.getChildAt(i).setVisibility(View.VISIBLE); diff --git a/src/org/kreed/vanilla/MediaAdapter.java b/src/org/kreed/vanilla/MediaAdapter.java index 075128ba..95c3929a 100644 --- a/src/org/kreed/vanilla/MediaAdapter.java +++ b/src/org/kreed/vanilla/MediaAdapter.java @@ -47,9 +47,9 @@ import java.io.Serializable; */ public class MediaAdapter extends CursorAdapter implements SectionIndexer { /** - * The activity that owns this adapter. + * A context to use. */ - private LibraryActivity mActivity; + private Context mContext; /** * The type of media represented by this adapter. Must be one of the * MediaUtils.FIELD_* constants. Determines which content provider to query for @@ -106,12 +106,16 @@ public class MediaAdapter extends CursorAdapter implements SectionIndexer { * The sort order for use with buildSongQuery(). */ private String mSongSort; + /** + * True if the data is stale and the query should be re-run. + */ + private boolean mNeedsRequery; /** * Construct a MediaAdapter representing the given type of * media. * - * @param activity The activity that owns this adapter. + * @param context A context to use. * @param type The type of media to represent. Must be one of the * Song.TYPE_* constants. This determines which content provider to query * and what fields to display in the views. @@ -120,16 +124,17 @@ public class MediaAdapter extends CursorAdapter implements SectionIndexer { * @param hasHeader Wether this view has a header row. * @param limiter An initial limiter to use */ - public MediaAdapter(LibraryActivity activity, int type, boolean expandable, boolean hasHeader, Limiter limiter) + public MediaAdapter(Context context, int type, boolean expandable, boolean hasHeader, Limiter limiter) { - super(activity, null, false); + super(context, null, false); - mActivity = activity; + mContext = context; mType = type; mExpandable = expandable; mHasHeader = hasHeader; mLimiter = limiter; mIndexer = new MusicAlphabetIndexer(1); + mNeedsRequery = true; switch (type) { case MediaUtils.TYPE_ARTIST: @@ -215,7 +220,7 @@ public class MediaAdapter extends CursorAdapter implements SectionIndexer { if (pos == 0) { MediaView view; if (convertView == null) - view = new MediaView(mActivity, mExpandable); + view = new MediaView(mContext, mExpandable); else view = (MediaView)convertView; view.makeHeader(mHeaderText); @@ -240,16 +245,33 @@ public class MediaAdapter extends CursorAdapter implements SectionIndexer { } /** - * Perform filtering on a background thread. + * Returns true if the data is stale and should be requeried. + */ + public boolean isRequeryNeeded() + { + return mNeedsRequery; + } + + /** + * Mark the current data as requiring a requery. + */ + public void requestRequery() + { + mNeedsRequery = true; + } + + /** + * Set a new filter. * - * @param constraint The terms to filter on, separated by spaces. Only + * The data should be requeried after calling this. + * + * @param filter The terms to filter on, separated by spaces. Only * media that contain all of the terms (in any order) will be displayed * after filtering is complete. */ - public void filter(String constraint) + public void setFilter(String filter) { - mConstraint = constraint; - mActivity.runQuery(this); + mConstraint = filter; } /** @@ -334,6 +356,7 @@ public class MediaAdapter extends CursorAdapter implements SectionIndexer { */ public QueryTask buildQuery() { + mNeedsRequery = false; return buildQuery(mProjection, false); } @@ -363,16 +386,18 @@ public class MediaAdapter extends CursorAdapter implements SectionIndexer { } /** - * Set the limiter for the adapter. A limiter is intended to restrict - * displayed media to only those that are children of a given parent - * media item. + * Set the limiter for the adapter. + * + * A limiter is intended to restrict displayed media to only those that are + * children of a given parent media item. + * + * The data should be requeried after calling this. * * @param limiter The limiter, created by {@link MediaAdapter#getLimiter(long)}. */ public final void setLimiter(Limiter limiter) { mLimiter = limiter; - mActivity.runQuery(this); } /**