The search now loads results async.

This commit is contained in:
Karim Abou Zeid 2016-03-21 00:51:14 +01:00
commit 9eb147625c
2 changed files with 103 additions and 51 deletions

View file

@ -20,9 +20,6 @@ import com.kabouzeid.gramophone.glide.SongGlideRequest;
import com.kabouzeid.gramophone.glide.artistimage.ArtistImage; import com.kabouzeid.gramophone.glide.artistimage.ArtistImage;
import com.kabouzeid.gramophone.helper.MusicPlayerRemote; import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
import com.kabouzeid.gramophone.helper.menu.SongMenuHelper; import com.kabouzeid.gramophone.helper.menu.SongMenuHelper;
import com.kabouzeid.gramophone.loader.AlbumLoader;
import com.kabouzeid.gramophone.loader.ArtistLoader;
import com.kabouzeid.gramophone.loader.SongLoader;
import com.kabouzeid.gramophone.model.Album; import com.kabouzeid.gramophone.model.Album;
import com.kabouzeid.gramophone.model.Artist; import com.kabouzeid.gramophone.model.Artist;
import com.kabouzeid.gramophone.model.Song; import com.kabouzeid.gramophone.model.Song;
@ -31,55 +28,36 @@ import com.kabouzeid.gramophone.util.MusicUtil;
import com.kabouzeid.gramophone.util.NavigationUtil; import com.kabouzeid.gramophone.util.NavigationUtil;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
* @author Karim Abou Zeid (kabouzeid) * @author Karim Abou Zeid (kabouzeid)
*/ */
public class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.ViewHolder> { public class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.ViewHolder> {
private static final int HEADER = 0; private static final int HEADER = 0;
private static final int ALBUM = 1; private static final int ALBUM = 1;
private static final int ARTIST = 2; private static final int ARTIST = 2;
private static final int SONG = 3; private static final int SONG = 3;
private final AppCompatActivity activity; private final AppCompatActivity activity;
private List results = Collections.emptyList(); private List<Object> dataSet;
public SearchAdapter(@NonNull AppCompatActivity activity) { public SearchAdapter(@NonNull AppCompatActivity activity, @NonNull List<Object> dataSet) {
this.activity = activity; this.activity = activity;
this.dataSet = dataSet;
} }
@SuppressWarnings("unchecked") public void swapDataSet(@NonNull List<Object> dataSet) {
public void search(@NonNull String query) { this.dataSet = dataSet;
results = new ArrayList();
if (!query.trim().equals("")) {
List songs = SongLoader.getSongs(activity, query);
if (!songs.isEmpty()) {
results.add(activity.getResources().getString(R.string.songs));
results.addAll(songs);
}
List artists = ArtistLoader.getArtists(activity, query);
if (!artists.isEmpty()) {
results.add(activity.getResources().getString(R.string.artists));
results.addAll(artists);
}
List albums = AlbumLoader.getAlbums(activity, query);
if (!albums.isEmpty()) {
results.add(activity.getResources().getString(R.string.albums));
results.addAll(albums);
}
}
notifyDataSetChanged(); notifyDataSetChanged();
} }
@Override @Override
public int getItemViewType(int position) { public int getItemViewType(int position) {
if (results.get(position) instanceof Album) return ALBUM; if (dataSet.get(position) instanceof Album) return ALBUM;
if (results.get(position) instanceof Artist) return ARTIST; if (dataSet.get(position) instanceof Artist) return ARTIST;
if (results.get(position) instanceof Song) return SONG; if (dataSet.get(position) instanceof Song) return SONG;
return HEADER; return HEADER;
} }
@ -96,7 +74,7 @@ public class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.ViewHolder
public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { public void onBindViewHolder(@NonNull final ViewHolder holder, int position) {
switch (getItemViewType(position)) { switch (getItemViewType(position)) {
case ALBUM: case ALBUM:
final Album album = (Album) results.get(position); final Album album = (Album) dataSet.get(position);
holder.title.setText(album.getTitle()); holder.title.setText(album.getTitle());
holder.text.setText(album.getArtistName()); holder.text.setText(album.getArtistName());
SongGlideRequest.Builder.from(Glide.with(activity), album.safeGetFirstSong()) SongGlideRequest.Builder.from(Glide.with(activity), album.safeGetFirstSong())
@ -104,7 +82,7 @@ public class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.ViewHolder
.into(holder.image); .into(holder.image);
break; break;
case ARTIST: case ARTIST:
final Artist artist = (Artist) results.get(position); final Artist artist = (Artist) dataSet.get(position);
holder.title.setText(artist.name); holder.title.setText(artist.name);
holder.text.setText(MusicUtil.getArtistInfoString(activity, artist)); holder.text.setText(MusicUtil.getArtistInfoString(activity, artist));
Glide.with(activity) Glide.with(activity)
@ -118,19 +96,19 @@ public class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.ViewHolder
.into(holder.image); .into(holder.image);
break; break;
case SONG: case SONG:
final Song song = (Song) results.get(position); final Song song = (Song) dataSet.get(position);
holder.title.setText(song.title); holder.title.setText(song.title);
holder.text.setText(song.albumName); holder.text.setText(song.albumName);
break; break;
default: default:
holder.title.setText(results.get(position).toString()); holder.title.setText(dataSet.get(position).toString());
break; break;
} }
} }
@Override @Override
public int getItemCount() { public int getItemCount() {
return results.size(); return dataSet.size();
} }
public class ViewHolder extends MediaEntryViewHolder { public class ViewHolder extends MediaEntryViewHolder {
@ -154,7 +132,7 @@ public class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.ViewHolder
menu.setOnClickListener(new SongMenuHelper.OnClickSongMenu(activity) { menu.setOnClickListener(new SongMenuHelper.OnClickSongMenu(activity) {
@Override @Override
public Song getSong() { public Song getSong() {
return (Song) results.get(getAdapterPosition()); return (Song) dataSet.get(getAdapterPosition());
} }
}); });
} else { } else {
@ -180,7 +158,7 @@ public class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.ViewHolder
@Override @Override
public void onClick(View view) { public void onClick(View view) {
Object item = results.get(getAdapterPosition()); Object item = dataSet.get(getAdapterPosition());
switch (getItemViewType()) { switch (getItemViewType()) {
case ALBUM: case ALBUM:
NavigationUtil.goToAlbum(activity, NavigationUtil.goToAlbum(activity,

View file

@ -1,7 +1,11 @@
package com.kabouzeid.gramophone.ui.activities; package com.kabouzeid.gramophone.ui.activities;
import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.support.v4.view.MenuItemCompat; import android.support.v4.view.MenuItemCompat;
import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
@ -16,15 +20,24 @@ import android.widget.TextView;
import com.kabouzeid.appthemehelper.ThemeStore; import com.kabouzeid.appthemehelper.ThemeStore;
import com.kabouzeid.gramophone.R; import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.adapter.SearchAdapter; import com.kabouzeid.gramophone.adapter.SearchAdapter;
import com.kabouzeid.gramophone.loader.AlbumLoader;
import com.kabouzeid.gramophone.loader.ArtistLoader;
import com.kabouzeid.gramophone.loader.SongLoader;
import com.kabouzeid.gramophone.misc.WrappedAsyncTaskLoader;
import com.kabouzeid.gramophone.ui.activities.base.AbsMusicServiceActivity; import com.kabouzeid.gramophone.ui.activities.base.AbsMusicServiceActivity;
import com.kabouzeid.gramophone.util.Util; import com.kabouzeid.gramophone.util.Util;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import butterknife.Bind; import butterknife.Bind;
import butterknife.ButterKnife; import butterknife.ButterKnife;
public class SearchActivity extends AbsMusicServiceActivity implements SearchView.OnQueryTextListener { public class SearchActivity extends AbsMusicServiceActivity implements SearchView.OnQueryTextListener, LoaderManager.LoaderCallbacks<List<Object>> {
public static final String TAG = SearchActivity.class.getSimpleName(); public static final String TAG = SearchActivity.class.getSimpleName();
private static final int LOADER_ID = 1;
@Bind(R.id.recycler_view) @Bind(R.id.recycler_view)
RecyclerView recyclerView; RecyclerView recyclerView;
@Bind(R.id.toolbar) @Bind(R.id.toolbar)
@ -34,9 +47,7 @@ public class SearchActivity extends AbsMusicServiceActivity implements SearchVie
SearchView searchView; SearchView searchView;
private SearchAdapter searchAdapter; private SearchAdapter adapter;
private String lastQuery = "";
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@ -50,8 +61,15 @@ public class SearchActivity extends AbsMusicServiceActivity implements SearchVie
setTaskDescriptionColorAuto(); setTaskDescriptionColorAuto();
recyclerView.setLayoutManager(new LinearLayoutManager(this)); recyclerView.setLayoutManager(new LinearLayoutManager(this));
searchAdapter = new SearchAdapter(this); adapter = new SearchAdapter(this, Collections.emptyList());
recyclerView.setAdapter(searchAdapter); adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
@Override
public void onChanged() {
super.onChanged();
empty.setVisibility(adapter.getItemCount() < 1 ? View.VISIBLE : View.GONE);
}
});
recyclerView.setAdapter(adapter);
recyclerView.setOnTouchListener(new View.OnTouchListener() { recyclerView.setOnTouchListener(new View.OnTouchListener() {
@Override @Override
@ -62,6 +80,8 @@ public class SearchActivity extends AbsMusicServiceActivity implements SearchVie
}); });
setUpToolBar(); setUpToolBar();
getSupportLoaderManager().initLoader(LOADER_ID, null, this);
} }
private void setUpToolBar() { private void setUpToolBar() {
@ -106,17 +126,18 @@ public class SearchActivity extends AbsMusicServiceActivity implements SearchVie
} }
private void search(@NonNull String query) { private void search(@NonNull String query) {
lastQuery = query; Loader loader = getSupportLoaderManager().getLoader(LOADER_ID);
if (searchAdapter != null) { AsyncSearchResultLoader asyncSearchResultLoader = (AsyncSearchResultLoader) loader;
searchAdapter.search(query); asyncSearchResultLoader.setQuery(query);
empty.setVisibility(searchAdapter.getItemCount() < 1 ? View.VISIBLE : View.GONE); asyncSearchResultLoader.forceLoad();
}
} }
@Override @Override
public void onMediaStoreChanged() { public void onMediaStoreChanged() {
super.onMediaStoreChanged(); super.onMediaStoreChanged();
search(lastQuery); Loader loader = getSupportLoaderManager().getLoader(LOADER_ID);
AsyncSearchResultLoader asyncSearchResultLoader = (AsyncSearchResultLoader) loader;
asyncSearchResultLoader.forceLoad();
} }
@Override @Override
@ -137,4 +158,57 @@ public class SearchActivity extends AbsMusicServiceActivity implements SearchVie
searchView.clearFocus(); searchView.clearFocus();
} }
} }
@Override
public Loader<List<Object>> onCreateLoader(int id, Bundle args) {
return new AsyncSearchResultLoader(this);
}
@Override
public void onLoadFinished(Loader<List<Object>> loader, List<Object> data) {
adapter.swapDataSet(data);
}
@Override
public void onLoaderReset(Loader<List<Object>> loader) {
adapter.swapDataSet(Collections.emptyList());
}
private static class AsyncSearchResultLoader extends WrappedAsyncTaskLoader<List<Object>> {
private String query;
public AsyncSearchResultLoader(Context context) {
super(context);
setUpdateThrottle(200);
}
public void setQuery(@Nullable String query) {
this.query = query;
}
@Override
public List<Object> loadInBackground() {
List<Object> results = new ArrayList<>();
if (query != null && !query.trim().equals("")) {
List songs = SongLoader.getSongs(getContext(), query);
if (!songs.isEmpty()) {
results.add(getContext().getResources().getString(R.string.songs));
results.addAll(songs);
}
List artists = ArtistLoader.getArtists(getContext(), query);
if (!artists.isEmpty()) {
results.add(getContext().getResources().getString(R.string.artists));
results.addAll(artists);
}
List albums = AlbumLoader.getAlbums(getContext(), query);
if (!albums.isEmpty()) {
results.add(getContext().getResources().getString(R.string.albums));
results.addAll(albums);
}
}
return results;
}
}
} }