Skip to content

Commit e9e9e80

Browse files
committed
Keep strong reference to Picasso thumbnail loading target
Before the Target would sometimes be garbage collected before being called with the loaded thumbnail, since Picasso holds weak references to targets
1 parent 49be75e commit e9e9e80

File tree

2 files changed

+47
-26
lines changed

2 files changed

+47
-26
lines changed

app/src/main/java/org/schabi/newpipe/player/Player.java

Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ public final class Player implements PlaybackListener, Listener {
174174
//////////////////////////////////////////////////////////////////////////*/
175175

176176
public static final int RENDERER_UNAVAILABLE = -1;
177+
private static final String PICASSO_PLAYER_THUMBNAIL_TAG = "PICASSO_PLAYER_THUMBNAIL_TAG";
177178

178179
/*//////////////////////////////////////////////////////////////////////////
179180
// Playback
@@ -232,6 +233,11 @@ public final class Player implements PlaybackListener, Listener {
232233
@NonNull private final SerialDisposable progressUpdateDisposable = new SerialDisposable();
233234
@NonNull private final CompositeDisposable databaseUpdateDisposable = new CompositeDisposable();
234235

236+
// This is the only listener we need for thumbnail loading, since there is always at most only
237+
// one thumbnail being loaded at a time. This field is also here to maintain a strong reference,
238+
// which would otherwise be garbage collected since Picasso holds weak references to targets.
239+
@NonNull private final Target currentThumbnailTarget;
240+
235241
/*//////////////////////////////////////////////////////////////////////////
236242
// Utils
237243
//////////////////////////////////////////////////////////////////////////*/
@@ -263,6 +269,8 @@ public Player(@NonNull final PlayerService service) {
263269
videoResolver = new VideoPlaybackResolver(context, dataSource, getQualityResolver());
264270
audioResolver = new AudioPlaybackResolver(context, dataSource);
265271

272+
currentThumbnailTarget = getCurrentThumbnailTarget();
273+
266274
// The UIs added here should always be present. They will be initialized when the player
267275
// reaches the initialization step. Make sure the media session ui is before the
268276
// notification ui in the UIs list, since the notification depends on the media session in
@@ -573,7 +581,7 @@ public void destroy() {
573581

574582
databaseUpdateDisposable.clear();
575583
progressUpdateDisposable.set(null);
576-
PicassoHelper.cancelTag(PicassoHelper.PLAYER_THUMBNAIL_TAG); // cancel thumbnail loading
584+
cancelLoadingCurrentThumbnail();
577585

578586
UIs.destroyAll(Object.class); // destroy every UI: obviously every UI extends Object
579587
}
@@ -747,48 +755,63 @@ private void unregisterBroadcastReceiver() {
747755
//////////////////////////////////////////////////////////////////////////*/
748756
//region Thumbnail loading
749757

750-
private void loadCurrentThumbnail(final String url) {
751-
if (DEBUG) {
752-
Log.d(TAG, "Thumbnail - loadCurrentThumbnail() called with url = ["
753-
+ (url == null ? "null" : url) + "]");
754-
}
755-
756-
// Unset currentThumbnail, since it is now outdated. This ensures it is not used in media
757-
// session metadata while the new thumbnail is being loaded by Picasso.
758-
currentThumbnail = null;
759-
if (isNullOrEmpty(url)) {
760-
return;
761-
}
762-
763-
// scale down the notification thumbnail for performance
764-
PicassoHelper.loadScaledDownThumbnail(context, url).into(new Target() {
758+
private Target getCurrentThumbnailTarget() {
759+
// a Picasso target is just a listener for thumbnail loading events
760+
return new Target() {
765761
@Override
766762
public void onBitmapLoaded(final Bitmap bitmap, final Picasso.LoadedFrom from) {
767763
if (DEBUG) {
768-
Log.d(TAG, "Thumbnail - onBitmapLoaded() called with: url = [" + url
769-
+ "], " + "bitmap = [" + bitmap + " -> " + bitmap.getWidth() + "x"
770-
+ bitmap.getHeight() + "], from = [" + from + "]");
764+
Log.d(TAG, "Thumbnail - onBitmapLoaded() called with: bitmap = [" + bitmap
765+
+ " -> " + bitmap.getWidth() + "x" + bitmap.getHeight() + "], from = ["
766+
+ from + "]");
771767
}
772-
773768
currentThumbnail = bitmap;
774-
// there is a new thumbnail, so changed the end screen thumbnail, too.
769+
// there is a new thumbnail, so e.g. the end screen thumbnail needs to change, too.
775770
UIs.call(playerUi -> playerUi.onThumbnailLoaded(bitmap));
776771
}
777772

778773
@Override
779774
public void onBitmapFailed(final Exception e, final Drawable errorDrawable) {
780-
Log.e(TAG, "Thumbnail - onBitmapFailed() called: url = [" + url + "]", e);
775+
Log.e(TAG, "Thumbnail - onBitmapFailed() called", e);
781776
currentThumbnail = null;
777+
// there is a new thumbnail, so e.g. the end screen thumbnail needs to change, too.
782778
UIs.call(playerUi -> playerUi.onThumbnailLoaded(null));
783779
}
784780

785781
@Override
786782
public void onPrepareLoad(final Drawable placeHolderDrawable) {
787783
if (DEBUG) {
788-
Log.d(TAG, "Thumbnail - onPrepareLoad() called: url = [" + url + "]");
784+
Log.d(TAG, "Thumbnail - onPrepareLoad() called");
789785
}
790786
}
791-
});
787+
};
788+
}
789+
790+
private void loadCurrentThumbnail(final String url) {
791+
if (DEBUG) {
792+
Log.d(TAG, "Thumbnail - loadCurrentThumbnail() called with url = ["
793+
+ (url == null ? "null" : url) + "]");
794+
}
795+
796+
// first cancel any previous loading
797+
cancelLoadingCurrentThumbnail();
798+
799+
// Unset currentThumbnail, since it is now outdated. This ensures it is not used in media
800+
// session metadata while the new thumbnail is being loaded by Picasso.
801+
currentThumbnail = null;
802+
if (isNullOrEmpty(url)) {
803+
return;
804+
}
805+
806+
// scale down the notification thumbnail for performance
807+
PicassoHelper.loadScaledDownThumbnail(context, url)
808+
.tag(PICASSO_PLAYER_THUMBNAIL_TAG)
809+
.into(currentThumbnailTarget);
810+
}
811+
812+
private void cancelLoadingCurrentThumbnail() {
813+
// cancel the Picasso job associated with the player thumbnail, if any
814+
PicassoHelper.cancelTag(PICASSO_PLAYER_THUMBNAIL_TAG);
792815
}
793816
//endregion
794817

app/src/main/java/org/schabi/newpipe/util/PicassoHelper.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030

3131
public final class PicassoHelper {
3232
private static final String TAG = PicassoHelper.class.getSimpleName();
33-
public static final String PLAYER_THUMBNAIL_TAG = "PICASSO_PLAYER_THUMBNAIL_TAG";
3433
private static final String PLAYER_THUMBNAIL_TRANSFORMATION_KEY =
3534
"PICASSO_PLAYER_THUMBNAIL_TRANSFORMATION_KEY";
3635

@@ -127,7 +126,6 @@ public static RequestCreator loadSeekbarThumbnailPreview(final String url) {
127126
public static RequestCreator loadScaledDownThumbnail(final Context context, final String url) {
128127
// scale down the notification thumbnail for performance
129128
return PicassoHelper.loadThumbnail(url)
130-
.tag(PLAYER_THUMBNAIL_TAG)
131129
.transform(new Transformation() {
132130
@Override
133131
public Bitmap transform(final Bitmap source) {

0 commit comments

Comments
 (0)