Only run queries for the active tab in the library

This commit is contained in:
Christopher Eby 2011-10-03 19:19:46 -05:00
parent de9793ca37
commit fdcf44f36d
2 changed files with 95 additions and 58 deletions

View File

@ -58,11 +58,6 @@ import android.widget.Toast;
* The library activity where songs to play can be selected from the library. * The library activity where songs to play can be selected from the library.
*/ */
public class LibraryActivity extends PlaybackActivity implements AdapterView.OnItemClickListener, TextWatcher { 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_PLAY = 0;
private static final int ACTION_ENQUEUE = 1; private static final int ACTION_ENQUEUE = 1;
private static final int ACTION_LAST_USED = 2; private static final int ACTION_LAST_USED = 2;
@ -101,7 +96,7 @@ public class LibraryActivity extends PlaybackActivity implements AdapterView.OnI
@Override @Override
public void onChange(boolean selfChange) public void onChange(boolean selfChange)
{ {
runQuery(mPlaylistAdapter); requestRequery(mPlaylistAdapter);
} }
}; };
@ -174,9 +169,6 @@ public class LibraryActivity extends PlaybackActivity implements AdapterView.OnI
if (state != null) if (state != null)
mTextFilter.setText(state.getString("filter")); mTextFilter.setText(state.getString("filter"));
// query adapters
onMediaChange();
} }
@Override @Override
@ -302,32 +294,37 @@ public class LibraryActivity extends PlaybackActivity implements AdapterView.OnI
*/ */
private int setLimiter(MediaAdapter.Limiter limiter) private int setLimiter(MediaAdapter.Limiter limiter)
{ {
int tab;
if (limiter == null) { if (limiter == null) {
mAlbumAdapter.setLimiter(null); mAlbumAdapter.setLimiter(null);
mSongAdapter.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) { requestRequery(mSongAdapter);
case MediaUtils.TYPE_ALBUM: requestRequery(mAlbumAdapter);
// Clear the cursor so we don't have the old selection showing when
// we switch to that tab. return 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);
}
} }
public void onItemClick(AdapterView<?> list, View view, int pos, long id) 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) public void onTextChanged(CharSequence text, int start, int before, int count)
{ {
MediaAdapter adapter = mCurrentAdapter; String filter = text.toString();
if (adapter != null) { for (MediaAdapter adapter : mAdapters) {
String filter = text.toString(); adapter.setFilter(filter);
adapter.filter(filter); requestRequery(adapter);
for (int i = TAB_COUNT; --i != -1; ) {
if (mAdapters[i] != adapter)
mAdapters[i].filter(filter);
}
} }
} }
@ -751,6 +743,23 @@ public class LibraryActivity extends PlaybackActivity implements AdapterView.OnI
return true; 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. * 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 @Override
public void onMediaChange() public void onMediaChange()
{ {
for (int i = 0; i != TAB_COUNT; ++i) for (MediaAdapter adapter : mAdapters)
runQuery(mAdapters[i]); requestRequery(adapter);
} }
private void setSearchBoxVisible(boolean visible) private void setSearchBoxVisible(boolean visible)
@ -811,7 +820,10 @@ public class LibraryActivity extends PlaybackActivity implements AdapterView.OnI
*/ */
private void setCurrentTab(int i) private void setCurrentTab(int i)
{ {
mCurrentAdapter = mAdapters[i]; MediaAdapter adapter = mAdapters[i];
mCurrentAdapter = adapter;
if (adapter.isRequeryNeeded())
runQuery(adapter);
mTabWidget.setCurrentTab(i); mTabWidget.setCurrentTab(i);
mLists.getChildAt(mCurrentTab).setVisibility(View.GONE); mLists.getChildAt(mCurrentTab).setVisibility(View.GONE);
mLists.getChildAt(i).setVisibility(View.VISIBLE); mLists.getChildAt(i).setVisibility(View.VISIBLE);

View File

@ -47,9 +47,9 @@ import java.io.Serializable;
*/ */
public class MediaAdapter extends CursorAdapter implements SectionIndexer { 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 * The type of media represented by this adapter. Must be one of the
* MediaUtils.FIELD_* constants. Determines which content provider to query for * 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(). * The sort order for use with buildSongQuery().
*/ */
private String mSongSort; 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 <code>type</code> of * Construct a MediaAdapter representing the given <code>type</code> of
* media. * 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 * @param type The type of media to represent. Must be one of the
* Song.TYPE_* constants. This determines which content provider to query * Song.TYPE_* constants. This determines which content provider to query
* and what fields to display in the views. * 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 hasHeader Wether this view has a header row.
* @param limiter An initial limiter to use * @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; mType = type;
mExpandable = expandable; mExpandable = expandable;
mHasHeader = hasHeader; mHasHeader = hasHeader;
mLimiter = limiter; mLimiter = limiter;
mIndexer = new MusicAlphabetIndexer(1); mIndexer = new MusicAlphabetIndexer(1);
mNeedsRequery = true;
switch (type) { switch (type) {
case MediaUtils.TYPE_ARTIST: case MediaUtils.TYPE_ARTIST:
@ -215,7 +220,7 @@ public class MediaAdapter extends CursorAdapter implements SectionIndexer {
if (pos == 0) { if (pos == 0) {
MediaView view; MediaView view;
if (convertView == null) if (convertView == null)
view = new MediaView(mActivity, mExpandable); view = new MediaView(mContext, mExpandable);
else else
view = (MediaView)convertView; view = (MediaView)convertView;
view.makeHeader(mHeaderText); 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 * media that contain all of the terms (in any order) will be displayed
* after filtering is complete. * after filtering is complete.
*/ */
public void filter(String constraint) public void setFilter(String filter)
{ {
mConstraint = constraint; mConstraint = filter;
mActivity.runQuery(this);
} }
/** /**
@ -334,6 +356,7 @@ public class MediaAdapter extends CursorAdapter implements SectionIndexer {
*/ */
public QueryTask buildQuery() public QueryTask buildQuery()
{ {
mNeedsRequery = false;
return buildQuery(mProjection, 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 * Set the limiter for the adapter.
* displayed media to only those that are children of a given parent *
* media item. * 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)}. * @param limiter The limiter, created by {@link MediaAdapter#getLimiter(long)}.
*/ */
public final void setLimiter(Limiter limiter) public final void setLimiter(Limiter limiter)
{ {
mLimiter = limiter; mLimiter = limiter;
mActivity.runQuery(this);
} }
/** /**