From d396e0120e6d8a910e2e36e80c2656c83b80d745 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Mon, 9 Nov 2015 17:35:11 -0800 Subject: #296 Improve low memory handling --- .../dsub/activity/SubsonicActivity.java | 1 + .../daneren2005/dsub/adapter/EntryGridAdapter.java | 3 +++ .../daneren2005/dsub/adapter/SettingsAdapter.java | 9 ++++++++- .../dsub/fragments/SelectDirectoryFragment.java | 12 +++++++++++- .../daneren2005/dsub/service/DownloadService.java | 6 ++++-- .../github/daneren2005/dsub/util/ImageLoader.java | 16 ++++++++++++---- .../daneren2005/dsub/view/RecyclingImageView.java | 22 +++++++++++++++++++--- 7 files changed, 58 insertions(+), 11 deletions(-) (limited to 'app/src/main/java/github/daneren2005') diff --git a/app/src/main/java/github/daneren2005/dsub/activity/SubsonicActivity.java b/app/src/main/java/github/daneren2005/dsub/activity/SubsonicActivity.java index 25acdd02..e055983e 100644 --- a/app/src/main/java/github/daneren2005/dsub/activity/SubsonicActivity.java +++ b/app/src/main/java/github/daneren2005/dsub/activity/SubsonicActivity.java @@ -216,6 +216,7 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte } populateTabs(); + getImageLoader().onUIVisible(); UpdateView.addActiveActivity(); } diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/EntryGridAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/EntryGridAdapter.java index d1ee4bea..38931482 100644 --- a/app/src/main/java/github/daneren2005/dsub/adapter/EntryGridAdapter.java +++ b/app/src/main/java/github/daneren2005/dsub/adapter/EntryGridAdapter.java @@ -117,6 +117,9 @@ public class EntryGridAdapter extends SectionAdapter { this.header = header; this.singleSectionHeader = true; } + public View getHeader() { + return header; + } public void setShowArtist(boolean showArtist) { this.showArtist = showArtist; diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/SettingsAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/SettingsAdapter.java index 0328e607..1cb9c34e 100644 --- a/app/src/main/java/github/daneren2005/dsub/adapter/SettingsAdapter.java +++ b/app/src/main/java/github/daneren2005/dsub/adapter/SettingsAdapter.java @@ -28,6 +28,7 @@ import java.util.List; import github.daneren2005.dsub.R; import github.daneren2005.dsub.domain.User; import github.daneren2005.dsub.util.ImageLoader; +import github.daneren2005.dsub.view.RecyclingImageView; import github.daneren2005.dsub.view.SettingView; import github.daneren2005.dsub.view.UpdateView; @@ -63,8 +64,14 @@ public class SettingsAdapter extends SectionAdapter { public void onBindHeaderHolder(UpdateView.UpdateViewHolder holder, String description) { View header = holder.getView(); - ImageView coverArtView = (ImageView) header.findViewById(R.id.user_avatar); + RecyclingImageView coverArtView = (RecyclingImageView) header.findViewById(R.id.user_avatar); imageLoader.loadAvatar(context, coverArtView, user.getUsername()); + coverArtView.setOnInvalidated(new RecyclingImageView.OnInvalidated() { + @Override + public void onInvalidated(RecyclingImageView imageView) { + imageLoader.loadAvatar(context, imageView, user.getUsername()); + } + }); TextView usernameView = (TextView) header.findViewById(R.id.user_username); usernameView.setText(user.getUsername()); diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java index 98467a2c..9bffbdfd 100644 --- a/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java +++ b/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java @@ -63,6 +63,7 @@ import github.daneren2005.dsub.util.Util; import github.daneren2005.dsub.view.FastScroller; import github.daneren2005.dsub.view.GridSpacingDecoration; import github.daneren2005.dsub.view.MyLeadingMarginSpan2; +import github.daneren2005.dsub.view.RecyclingImageView; import github.daneren2005.dsub.view.UpdateView; import java.util.ArrayList; @@ -1112,8 +1113,10 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section } private void setupCoverArt(View header) { + setupCoverArtImpl((RecyclingImageView) header.findViewById(R.id.select_album_art)); + } + private void setupCoverArtImpl(RecyclingImageView coverArtView) { final ImageLoader imageLoader = getImageLoader(); - View coverArtView = header.findViewById(R.id.select_album_art); // Try a few times to get a random cover art if(artistInfo != null) { @@ -1164,6 +1167,13 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section }); imageLoader.loadImage(coverArtView, albumRep, false, true); } + + coverArtView.setOnInvalidated(new RecyclingImageView.OnInvalidated() { + @Override + public void onInvalidated(RecyclingImageView imageView) { + setupCoverArtImpl(imageView); + } + }); } private void setupTextDisplay(final View header) { final TextView titleView = (TextView) header.findViewById(R.id.select_album_title); diff --git a/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java b/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java index 7275e447..bfc9c5d6 100644 --- a/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java +++ b/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java @@ -283,9 +283,9 @@ public class DownloadService extends Service { @Override public void onTrimMemory(int level) { - Log.w(TAG, "Level: " + level); ImageLoader imageLoader = SubsonicActivity.getStaticImageLoader(this); if(imageLoader != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + Log.i(TAG, "Memory Trim Level: " + level); if (level < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) { if (level >= ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL) { imageLoader.onLowMemory(0.75f); @@ -294,8 +294,10 @@ public class DownloadService extends Service { } else if(level >= ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE) { imageLoader.onLowMemory(0.25f); } - } else if (level >= TRIM_MEMORY_MODERATE) { + } else if (level >= ComponentCallbacks2.TRIM_MEMORY_MODERATE) { imageLoader.onLowMemory(0.25f); + } else if(level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE) { + imageLoader.onLowMemory(0.75f); } } } diff --git a/app/src/main/java/github/daneren2005/dsub/util/ImageLoader.java b/app/src/main/java/github/daneren2005/dsub/util/ImageLoader.java index 7ae1648f..c10158d2 100644 --- a/app/src/main/java/github/daneren2005/dsub/util/ImageLoader.java +++ b/app/src/main/java/github/daneren2005/dsub/util/ImageLoader.java @@ -116,7 +116,14 @@ public class ImageLoader { }.execute(); } public void onLowMemory(float percent) { - cache.trimToSize(Math.round(cacheSize * percent)); + Log.i(TAG, "Cache size: " + cache.size() + " => " + Math.round(cacheSize * (1 - percent)) + " out of " + cache.maxSize()); + cache.resize(Math.round(cacheSize * (1 - percent))); + } + public void onUIVisible() { + if(cache.maxSize() != cacheSize) { + Log.i(TAG, "Returned to full cache size"); + cache.resize(cacheSize); + } } private Bitmap getUnknownImage(MusicDirectory.Entry entry, int size) { @@ -388,10 +395,11 @@ public class ImageLoader { private void setImage(MusicDirectory.Entry entry, RemoteControlClientBase remoteControl, Drawable drawable) { if(remoteControl != null && drawable != null) { Bitmap origBitmap = ((BitmapDrawable)drawable).getBitmap(); - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2 && origBitmap != null) { - origBitmap = origBitmap.copy(origBitmap.getConfig(), false); - } if ( origBitmap != null && !origBitmap.isRecycled()) { + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2 && origBitmap != null) { + origBitmap = origBitmap.copy(origBitmap.getConfig(), false); + } + remoteControl.updateAlbumArt(entry, origBitmap); } else { if(origBitmap != null) { diff --git a/app/src/main/java/github/daneren2005/dsub/view/RecyclingImageView.java b/app/src/main/java/github/daneren2005/dsub/view/RecyclingImageView.java index a7208cee..501b363d 100644 --- a/app/src/main/java/github/daneren2005/dsub/view/RecyclingImageView.java +++ b/app/src/main/java/github/daneren2005/dsub/view/RecyclingImageView.java @@ -28,6 +28,7 @@ import android.widget.ImageView; public class RecyclingImageView extends ImageView { private boolean invalidated = false; + private OnInvalidated onInvalidated; public RecyclingImageView(Context context) { super(context); @@ -53,7 +54,7 @@ public class RecyclingImageView extends ImageView { if(drawable instanceof BitmapDrawable) { if (isBitmapRecycled(drawable)) { this.setImageDrawable(null); - invalidated = true; + setInvalidated(true); } } else if(drawable instanceof TransitionDrawable) { TransitionDrawable transitionDrawable = (TransitionDrawable) drawable; @@ -62,7 +63,7 @@ public class RecyclingImageView extends ImageView { Drawable lastDrawable = transitionDrawable.getDrawable(transitionDrawable.getNumberOfLayers() - 1); if(isBitmapRecycled(lastDrawable)) { this.setImageDrawable(null); - invalidated = true; + setInvalidated(true); } else { // Go through earlier bitmaps and make sure that they are not recycled for (int i = 0; i < transitionDrawable.getNumberOfLayers(); i++) { @@ -83,7 +84,7 @@ public class RecyclingImageView extends ImageView { @Override public void setImageDrawable(Drawable drawable) { super.setImageDrawable(drawable); - invalidated = false; + setInvalidated(false); } private boolean isBitmapRecycled(Drawable drawable) { @@ -99,7 +100,22 @@ public class RecyclingImageView extends ImageView { } } + public void setInvalidated(boolean invalidated) { + this.invalidated = invalidated; + + if(invalidated && onInvalidated != null) { + onInvalidated.onInvalidated(this); + } + } public boolean isInvalidated() { return invalidated; } + + public void setOnInvalidated(OnInvalidated onInvalidated) { + this.onInvalidated = onInvalidated; + } + + public interface OnInvalidated { + void onInvalidated(RecyclingImageView imageView); + } } -- cgit v1.2.3