Replaced Ion with Glide. Big performance boost, and should also fix the FCs many people get because of recycled bitmaps. Fixed the ripple flickering by using ?selectableItemBackground on Lollipop again instead of custom ripple. Search is broken for now, remake in progress.

This commit is contained in:
Karim Abou Zeid 2015-04-22 21:17:38 +02:00
commit ee2b661eb4
34 changed files with 448 additions and 667 deletions

View file

@ -2,6 +2,7 @@ package com.kabouzeid.gramophone.adapter;
import android.app.Activity;
import android.graphics.Bitmap;
import android.net.Uri;
import android.support.v4.util.Pair;
import android.support.v7.graphics.Palette;
import android.support.v7.widget.RecyclerView;
@ -12,6 +13,12 @@ import android.widget.ImageView;
import android.widget.TextView;
import com.afollestad.materialdialogs.util.DialogUtils;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.GlideBitmapDrawable;
import com.bumptech.glide.load.resource.drawable.GlideDrawable;
import com.bumptech.glide.request.Request;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.target.Target;
import com.kabouzeid.gramophone.App;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.loader.AlbumLoader;
@ -23,11 +30,6 @@ import com.kabouzeid.gramophone.util.MusicUtil;
import com.kabouzeid.gramophone.util.NavigationUtil;
import com.kabouzeid.gramophone.util.PreferenceUtils;
import com.kabouzeid.gramophone.util.ViewUtil;
import com.koushikdutta.async.future.Future;
import com.koushikdutta.async.future.FutureCallback;
import com.koushikdutta.ion.ImageViewBitmapInfo;
import com.koushikdutta.ion.Ion;
import com.koushikdutta.ion.bitmap.BitmapInfo;
import com.squareup.otto.Subscribe;
import java.util.List;
@ -51,9 +53,9 @@ public class AlbumAdapter extends RecyclerView.Adapter<AlbumAdapter.ViewHolder>
@Override
public void onViewRecycled(ViewHolder holder) {
super.onViewRecycled(holder);
Object tag = holder.image.getTag();
if (tag instanceof Future) {
((Future) tag).cancel();
Object tag = holder.albumArt.getTag();
if (tag instanceof Request) {
((Request) tag).clear();
}
}
@ -63,35 +65,30 @@ public class AlbumAdapter extends RecyclerView.Adapter<AlbumAdapter.ViewHolder>
resetColors(holder.title, holder.artist, holder.footer);
holder.title.setText(album.title);
holder.artist.setText(album.artistName);
holder.image.setTag(
Ion.with(activity)
.load(MusicUtil.getAlbumArtUri(album.id).toString())
.withBitmap()
.resize(holder.image.getWidth(), holder.image.getHeight())
.centerCrop()
.intoImageView(holder.image)
.withBitmapInfo()
.setCallback(new FutureCallback<ImageViewBitmapInfo>() {
holder.albumArt.setTag(
Glide.with(activity)
.loadFromMediaStore(MusicUtil.getAlbumArtUri(album.id))
.error(R.drawable.default_album_art)
.listener(new RequestListener<Uri, GlideDrawable>() {
@Override
public void onCompleted(Exception e, ImageViewBitmapInfo result) {
if (result != null) {
BitmapInfo info = result.getBitmapInfo();
if (info != null) {
Bitmap bitmap = info.bitmap;
if (bitmap != null) {
if (usePalette)
applyPalette(bitmap, holder.title, holder.artist, holder.footer);
return;
}
}
}
holder.image.setImageResource(R.drawable.default_album_art);
public boolean onException(Exception e, Uri model, Target<GlideDrawable> target, boolean isFirstResource) {
if (usePalette)
paletteBlackAndWhite(holder.title, holder.artist, holder.footer);
applyPalette(null, holder.title, holder.artist, holder.footer);
return false;
}
@Override
public boolean onResourceReady(GlideDrawable resource, Uri model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
if (usePalette)
applyPalette(((GlideBitmapDrawable) resource).getBitmap(), holder.title, holder.artist, holder.footer);
return false;
}
})
.into(holder.albumArt)
.getRequest()
);
}
@ -101,14 +98,14 @@ public class AlbumAdapter extends RecyclerView.Adapter<AlbumAdapter.ViewHolder>
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
final ImageView image;
final ImageView albumArt;
final TextView title;
final TextView artist;
final View footer;
public ViewHolder(View itemView) {
super(itemView);
image = (ImageView) itemView.findViewById(R.id.album_art);
albumArt = (ImageView) itemView.findViewById(R.id.album_art);
title = (TextView) itemView.findViewById(R.id.album_title);
artist = (TextView) itemView.findViewById(R.id.album_interpret);
footer = itemView.findViewById(R.id.footer);
@ -118,7 +115,7 @@ public class AlbumAdapter extends RecyclerView.Adapter<AlbumAdapter.ViewHolder>
@Override
public void onClick(View v) {
Pair[] albumPairs = new Pair[]{
Pair.create(image,
Pair.create(albumArt,
activity.getResources().getString(R.string.transition_album_cover)
)};
if (activity instanceof AbsFabActivity)
@ -138,20 +135,24 @@ public class AlbumAdapter extends RecyclerView.Adapter<AlbumAdapter.ViewHolder>
}
private void applyPalette(Bitmap bitmap, final TextView title, final TextView artist, final View footer) {
Palette.from(bitmap)
.generate(new Palette.PaletteAsyncListener() {
@Override
public void onGenerated(Palette palette) {
final Palette.Swatch vibrantSwatch = palette.getVibrantSwatch();
if (vibrantSwatch != null) {
title.setTextColor(vibrantSwatch.getTitleTextColor());
artist.setTextColor(vibrantSwatch.getTitleTextColor());
ViewUtil.animateViewColor(footer, DialogUtils.resolveColor(activity, R.attr.default_bar_color), vibrantSwatch.getRgb());
} else {
paletteBlackAndWhite(title, artist, footer);
if (bitmap != null) {
Palette.from(bitmap)
.generate(new Palette.PaletteAsyncListener() {
@Override
public void onGenerated(Palette palette) {
final Palette.Swatch vibrantSwatch = palette.getVibrantSwatch();
if (vibrantSwatch != null) {
title.setTextColor(vibrantSwatch.getTitleTextColor());
artist.setTextColor(vibrantSwatch.getTitleTextColor());
ViewUtil.animateViewColor(footer, DialogUtils.resolveColor(activity, R.attr.default_bar_color), vibrantSwatch.getRgb());
} else {
paletteBlackAndWhite(title, artist, footer);
}
}
}
});
});
} else {
paletteBlackAndWhite(title, artist, footer);
}
}
private void paletteBlackAndWhite(final TextView title, final TextView artist, final View footer) {

View file

@ -1,7 +1,6 @@
package com.kabouzeid.gramophone.adapter;
import android.app.Activity;
import android.graphics.Bitmap;
import android.support.v4.util.Pair;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
@ -10,6 +9,7 @@ import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.kabouzeid.gramophone.App;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.lastfm.artist.LastFMArtistThumbnailUrlLoader;
@ -17,9 +17,8 @@ import com.kabouzeid.gramophone.loader.ArtistLoader;
import com.kabouzeid.gramophone.model.Artist;
import com.kabouzeid.gramophone.model.DataBaseChangedEvent;
import com.kabouzeid.gramophone.ui.activities.base.AbsFabActivity;
import com.kabouzeid.gramophone.util.MusicUtil;
import com.kabouzeid.gramophone.util.NavigationUtil;
import com.koushikdutta.async.future.FutureCallback;
import com.koushikdutta.ion.Ion;
import com.squareup.otto.Subscribe;
import java.util.List;
@ -51,25 +50,16 @@ public class ArtistAdapter extends RecyclerView.Adapter<ArtistAdapter.ViewHolder
final Artist artist = dataSet.get(position);
holder.artistName.setText(artist.name);
holder.artistInfo.setText(artist.getSubTitle());
holder.artistInfo.setText(MusicUtil.getArtistInfoString(activity, artist));
holder.artistImage.setImageResource(R.drawable.default_artist_image);
LastFMArtistThumbnailUrlLoader.loadArtistThumbnailUrl(activity, artist.name, false, new LastFMArtistThumbnailUrlLoader.ArtistThumbnailUrlLoaderCallback() {
@Override
public void onArtistThumbnailUrlLoaded(final String url) {
Ion.with(activity)
Glide.with(activity)
.load(url)
.asBitmap()
.setCallback(new FutureCallback<Bitmap>() {
@Override
public void onCompleted(Exception e, Bitmap result) {
if (result != null)
holder.artistImage.setImageBitmap(result);
else {
holder.artistImage.setImageResource(R.drawable.default_artist_image);
}
}
});
.error(R.drawable.default_artist_image)
.into(holder.artistImage);
}
});
}

View file

@ -9,12 +9,13 @@ import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.Request;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.model.Album;
import com.kabouzeid.gramophone.ui.activities.base.AbsFabActivity;
import com.kabouzeid.gramophone.util.MusicUtil;
import com.kabouzeid.gramophone.util.NavigationUtil;
import com.koushikdutta.ion.Ion;
import java.util.List;
@ -44,17 +45,25 @@ public class ArtistAlbumAdapter extends RecyclerView.Adapter<ArtistAlbumAdapter.
return new ViewHolder(view);
}
@Override
public void onViewRecycled(ViewHolder holder) {
super.onViewRecycled(holder);
Object tag = holder.albumArt.getTag();
if (tag instanceof Request) {
((Request) tag).clear();
}
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
final Album album = dataSet.get(position);
Ion.with(activity)
.load(MusicUtil.getAlbumArtUri(album.id).toString())
.withBitmap()
.resize(holder.albumArt.getWidth(), holder.albumArt.getHeight())
.centerCrop()
.error(R.drawable.default_album_art)
.intoImageView(holder.albumArt);
holder.albumArt.setTag(Glide.with(activity)
.loadFromMediaStore(MusicUtil.getAlbumArtUri(album.id))
.error(R.drawable.default_album_art)
.into(holder.albumArt)
.getRequest()
);
holder.title.setText(album.title);
holder.year.setText(String.valueOf(album.year));

View file

@ -1,91 +1,39 @@
package com.kabouzeid.gramophone.adapter;
import android.graphics.Color;
import android.graphics.Typeface;
import android.app.Activity;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.PopupMenu;
import android.widget.TextView;
import com.afollestad.materialdialogs.util.DialogUtils;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.helper.MenuItemClickHelper;
import com.kabouzeid.gramophone.model.SearchEntry;
import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.ui.activities.SearchActivity;
import java.util.List;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class SearchAdapter extends ArrayAdapter<SearchEntry> {
public class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.ViewHolder> {
private Activity activity;
private final AppCompatActivity activity;
public SearchAdapter(AppCompatActivity activity, List<SearchEntry> objects) {
super(activity, R.layout.item_list_search, objects);
public SearchAdapter(AppCompatActivity activity) {
this.activity = activity;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_list_search, parent, false);
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return null;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
}
@Override
public int getItemCount() {
return 0;
}
public class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View itemView) {
super(itemView);
}
final SearchEntry item = getItem(position);
final TextView title = (TextView) convertView.findViewById(R.id.title);
final TextView subTitle = (TextView) convertView.findViewById(R.id.sub_title);
final ImageView imageView = (ImageView) convertView.findViewById(R.id.image);
final ImageView overflowButton = (ImageView) convertView.findViewById(R.id.menu);
if (item instanceof SearchActivity.LabelEntry) {
title.setTypeface(null, Typeface.BOLD);
subTitle.setVisibility(View.GONE);
imageView.setVisibility(View.GONE);
overflowButton.setVisibility(View.GONE);
convertView.setBackgroundColor(DialogUtils.resolveColor(getContext(), R.attr.default_bar_color));
} else if (item instanceof Song) {
title.setTypeface(null, Typeface.NORMAL);
subTitle.setVisibility(View.VISIBLE);
imageView.setVisibility(View.GONE);
convertView.setBackgroundColor(Color.TRANSPARENT);
overflowButton.setVisibility(View.VISIBLE);
overflowButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
PopupMenu popupMenu = new PopupMenu(activity, view);
popupMenu.inflate(R.menu.menu_item_song);
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
return MenuItemClickHelper.handleSongMenuClick(activity, (Song) item, menuItem);
}
});
popupMenu.show();
}
});
} else {
title.setTypeface(null, Typeface.NORMAL);
subTitle.setVisibility(View.VISIBLE);
imageView.setVisibility(View.VISIBLE);
overflowButton.setVisibility(View.GONE);
convertView.setBackgroundColor(Color.TRANSPARENT);
}
title.setText(item.getTitle());
subTitle.setText(item.getSubTitle());
imageView.setImageBitmap(null);
item.loadImage(getContext(), imageView);
return convertView;
}
}

View file

@ -11,13 +11,13 @@ import android.widget.ImageView;
import android.widget.PopupMenu;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.helper.MenuItemClickHelper;
import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.ui.activities.base.AbsFabActivity;
import com.kabouzeid.gramophone.util.MusicUtil;
import com.kabouzeid.gramophone.util.NavigationUtil;
import com.koushikdutta.ion.Ion;
import java.util.List;
@ -47,13 +47,10 @@ public class ArtistSongAdapter extends ArrayAdapter<Song> {
songTitle.setText(song.title);
songInfo.setText(song.albumName);
Ion.with(activity)
.load(MusicUtil.getAlbumArtUri(song.albumId).toString())
.withBitmap()
.resize(albumArt.getWidth(), albumArt.getHeight())
.centerCrop()
Glide.with(activity)
.loadFromMediaStore(MusicUtil.getAlbumArtUri(song.albumId))
.error(R.drawable.default_album_art)
.intoImageView(albumArt);
.into(albumArt);
final ImageView overflowButton = (ImageView) convertView.findViewById(R.id.menu);
overflowButton.setOnClickListener(new View.OnClickListener() {

View file

@ -11,6 +11,8 @@ import android.widget.ImageView;
import android.widget.PopupMenu;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.Request;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.helper.MenuItemClickHelper;
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
@ -20,7 +22,6 @@ import com.kabouzeid.gramophone.ui.activities.base.AbsFabActivity;
import com.kabouzeid.gramophone.util.MusicUtil;
import com.kabouzeid.gramophone.util.NavigationUtil;
import com.kabouzeid.gramophone.util.PlaylistsUtil;
import com.koushikdutta.ion.Ion;
import java.util.ArrayList;
import java.util.List;
@ -48,6 +49,10 @@ public class PlaylistSongAdapter extends RecyclerView.Adapter<PlaylistSongAdapte
@Override
public void onViewRecycled(ViewHolder holder) {
super.onViewRecycled(holder);
Object tag = holder.albumArt.getTag();
if (tag instanceof Request) {
((Request) tag).clear();
}
}
@Override
@ -56,15 +61,12 @@ public class PlaylistSongAdapter extends RecyclerView.Adapter<PlaylistSongAdapte
holder.songTitle.setText(song.title);
holder.songInfo.setText(song.artistName);
holder.albumArt.setTag(
Ion.with(activity)
.load(MusicUtil.getAlbumArtUri(song.albumId).toString())
.withBitmap()
.resize(holder.albumArt.getWidth(), holder.albumArt.getHeight())
.centerCrop()
Glide.with(activity)
.loadFromMediaStore(MusicUtil.getAlbumArtUri(song.albumId))
.error(R.drawable.default_album_art)
.intoImageView(holder.albumArt)
.into(holder.albumArt)
.getRequest()
);
}

View file

@ -13,6 +13,8 @@ import android.widget.PopupMenu;
import android.widget.TextView;
import com.afollestad.materialdialogs.ThemeSingleton;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.Request;
import com.kabouzeid.gramophone.App;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.helper.MenuItemClickHelper;
@ -23,7 +25,6 @@ import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.ui.activities.base.AbsFabActivity;
import com.kabouzeid.gramophone.util.MusicUtil;
import com.kabouzeid.gramophone.util.NavigationUtil;
import com.koushikdutta.ion.Ion;
import com.squareup.otto.Subscribe;
import java.util.ArrayList;
@ -55,6 +56,15 @@ public class SongAdapter extends RecyclerView.Adapter<SongAdapter.ViewHolder> {
return new ViewHolder(view);
}
@Override
public void onViewRecycled(ViewHolder holder) {
super.onViewRecycled(holder);
Object tag = holder.albumArt.getTag();
if (tag instanceof Request) {
((Request) tag).clear();
}
}
@Override
public int getItemViewType(int position) {
return position == 0 ? SHUFFLE_BUTTON : SONG;
@ -67,14 +77,13 @@ public class SongAdapter extends RecyclerView.Adapter<SongAdapter.ViewHolder> {
holder.songTitle.setText(song.title);
holder.songInfo.setText(song.artistName);
Ion.with(activity)
.load(MusicUtil.getAlbumArtUri(song.albumId).toString())
.withBitmap()
.resize(holder.albumArt.getWidth(), holder.albumArt.getHeight())
.centerCrop()
.error(R.drawable.default_album_art)
.intoImageView(holder.albumArt);
holder.albumArt.setTag(
Glide.with(activity)
.loadFromMediaStore(MusicUtil.getAlbumArtUri(song.albumId))
.error(R.drawable.default_album_art)
.into(holder.albumArt)
.getRequest()
);
} else {
holder.songTitle.setText(activity.getResources().getString(R.string.shuffle_all).toUpperCase());
holder.songTitle.setTextColor(ThemeSingleton.get().positiveColor);