Merge pull request #13272 from theimpulson/coilport
Migrate from Picasso to Coil
This commit is contained in:
commit
9f193a3b00
107 changed files with 715 additions and 915 deletions
|
|
@ -46,13 +46,14 @@ import static org.schabi.newpipe.util.ListHelper.getPopupResolutionIndex;
|
|||
import static org.schabi.newpipe.util.ListHelper.getResolutionIndex;
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
|
||||
import static coil3.Image_androidKt.toBitmap;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.media.AudioManager;
|
||||
import android.support.v4.media.session.MediaSessionCompat;
|
||||
import android.util.Log;
|
||||
|
|
@ -80,8 +81,6 @@ import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
|
|||
import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
|
||||
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
|
||||
import com.google.android.exoplayer2.video.VideoSize;
|
||||
import com.squareup.picasso.Picasso;
|
||||
import com.squareup.picasso.Target;
|
||||
|
||||
import org.schabi.newpipe.MainActivity;
|
||||
import org.schabi.newpipe.R;
|
||||
|
|
@ -126,13 +125,14 @@ import org.schabi.newpipe.util.ListHelper;
|
|||
import org.schabi.newpipe.util.NavigationHelper;
|
||||
import org.schabi.newpipe.util.SerializedCache;
|
||||
import org.schabi.newpipe.util.StreamTypeUtil;
|
||||
import org.schabi.newpipe.util.image.PicassoHelper;
|
||||
import org.schabi.newpipe.util.image.CoilHelper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import coil3.target.Target;
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.rxjava3.core.Observable;
|
||||
import io.reactivex.rxjava3.core.Single;
|
||||
|
|
@ -181,7 +181,6 @@ public final class Player implements PlaybackListener, Listener {
|
|||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
public static final int RENDERER_UNAVAILABLE = -1;
|
||||
private static final String PICASSO_PLAYER_THUMBNAIL_TAG = "PICASSO_PLAYER_THUMBNAIL_TAG";
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Playback
|
||||
|
|
@ -200,6 +199,8 @@ public final class Player implements PlaybackListener, Listener {
|
|||
private MediaItemTag currentMetadata;
|
||||
@Nullable
|
||||
private Bitmap currentThumbnail;
|
||||
@Nullable
|
||||
private coil3.request.Disposable thumbnailDisposable;
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Player
|
||||
|
|
@ -255,12 +256,6 @@ public final class Player implements PlaybackListener, Listener {
|
|||
@NonNull
|
||||
private final CompositeDisposable streamItemDisposable = new CompositeDisposable();
|
||||
|
||||
// This is the only listener we need for thumbnail loading, since there is always at most only
|
||||
// one thumbnail being loaded at a time. This field is also here to maintain a strong reference,
|
||||
// which would otherwise be garbage collected since Picasso holds weak references to targets.
|
||||
@NonNull
|
||||
private final Target currentThumbnailTarget;
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Utils
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
|
@ -314,8 +309,6 @@ public final class Player implements PlaybackListener, Listener {
|
|||
videoResolver = new VideoPlaybackResolver(context, dataSource, getQualityResolver());
|
||||
audioResolver = new AudioPlaybackResolver(context, dataSource);
|
||||
|
||||
currentThumbnailTarget = getCurrentThumbnailTarget();
|
||||
|
||||
// The UIs added here should always be present. They will be initialized when the player
|
||||
// reaches the initialization step. Make sure the media session ui is before the
|
||||
// notification ui in the UIs list, since the notification depends on the media session in
|
||||
|
|
@ -704,7 +697,6 @@ public final class Player implements PlaybackListener, Listener {
|
|||
databaseUpdateDisposable.clear();
|
||||
progressUpdateDisposable.set(null);
|
||||
streamItemDisposable.clear();
|
||||
cancelLoadingCurrentThumbnail();
|
||||
|
||||
UIs.destroyAll(Object.class); // destroy every UI: obviously every UI extends Object
|
||||
}
|
||||
|
|
@ -884,67 +876,58 @@ public final class Player implements PlaybackListener, Listener {
|
|||
//////////////////////////////////////////////////////////////////////////*/
|
||||
//region Thumbnail loading
|
||||
|
||||
private Target getCurrentThumbnailTarget() {
|
||||
// a Picasso target is just a listener for thumbnail loading events
|
||||
return new Target() {
|
||||
@Override
|
||||
public void onBitmapLoaded(final Bitmap bitmap, final Picasso.LoadedFrom from) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Thumbnail - onBitmapLoaded() called with: bitmap = [" + bitmap
|
||||
+ " -> " + bitmap.getWidth() + "x" + bitmap.getHeight() + "], from = ["
|
||||
+ from + "]");
|
||||
}
|
||||
// there is a new thumbnail, so e.g. the end screen thumbnail needs to change, too.
|
||||
onThumbnailLoaded(bitmap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBitmapFailed(final Exception e, final Drawable errorDrawable) {
|
||||
Log.e(TAG, "Thumbnail - onBitmapFailed() called", e);
|
||||
// there is a new thumbnail, so e.g. the end screen thumbnail needs to change, too.
|
||||
onThumbnailLoaded(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepareLoad(final Drawable placeHolderDrawable) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Thumbnail - onPrepareLoad() called");
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void loadCurrentThumbnail(final List<Image> thumbnails) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Thumbnail - loadCurrentThumbnail() called with thumbnails = ["
|
||||
+ thumbnails.size() + "]");
|
||||
}
|
||||
|
||||
// first cancel any previous loading
|
||||
cancelLoadingCurrentThumbnail();
|
||||
// Cancel any ongoing image loading
|
||||
if (thumbnailDisposable != null) {
|
||||
thumbnailDisposable.dispose();
|
||||
}
|
||||
|
||||
// Unset currentThumbnail, since it is now outdated. This ensures it is not used in media
|
||||
// session metadata while the new thumbnail is being loaded by Picasso.
|
||||
// session metadata while the new thumbnail is being loaded by Coil.
|
||||
onThumbnailLoaded(null);
|
||||
if (thumbnails.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// scale down the notification thumbnail for performance
|
||||
PicassoHelper.loadScaledDownThumbnail(context, thumbnails)
|
||||
.tag(PICASSO_PLAYER_THUMBNAIL_TAG)
|
||||
.into(currentThumbnailTarget);
|
||||
final var thumbnailTarget = new Target() {
|
||||
@Override
|
||||
public void onError(@Nullable final coil3.Image error) {
|
||||
Log.e(TAG, "Thumbnail - onError() called");
|
||||
// there is a new thumbnail, so e.g. the end screen thumbnail needs to change, too.
|
||||
onThumbnailLoaded(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart(@Nullable final coil3.Image placeholder) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Thumbnail - onStart() called");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(@NonNull final coil3.Image result) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Thumbnail - onSuccess() called with: drawable = [" + result + "]");
|
||||
}
|
||||
// there is a new thumbnail, so e.g. the end screen thumbnail needs to change, too.
|
||||
onThumbnailLoaded(toBitmap(result));
|
||||
}
|
||||
};
|
||||
thumbnailDisposable = CoilHelper.INSTANCE
|
||||
.loadScaledDownThumbnail(context, thumbnails, thumbnailTarget);
|
||||
}
|
||||
|
||||
private void cancelLoadingCurrentThumbnail() {
|
||||
// cancel the Picasso job associated with the player thumbnail, if any
|
||||
PicassoHelper.cancelTag(PICASSO_PLAYER_THUMBNAIL_TAG);
|
||||
}
|
||||
|
||||
private void onThumbnailLoaded(@Nullable final Bitmap bitmap) {
|
||||
// Avoid useless thumbnail updates, if the thumbnail has not actually changed. Based on the
|
||||
// thumbnail loading code, this if would be skipped only when both bitmaps are `null`, since
|
||||
// onThumbnailLoaded won't be called twice with the same nonnull bitmap by Picasso's target.
|
||||
// onThumbnailLoaded won't be called twice with the same nonnull bitmap by Coil's target.
|
||||
if (currentThumbnail != bitmap) {
|
||||
currentThumbnail = bitmap;
|
||||
UIs.call(playerUi -> playerUi.onThumbnailLoaded(bitmap));
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ public final class PlayerHolder {
|
|||
// helper to handle context in common place as using the same
|
||||
// context to bind/unbind a service is crucial
|
||||
private Context getCommonContext() {
|
||||
return App.getApp();
|
||||
return App.getInstance();
|
||||
}
|
||||
|
||||
public void startService(final boolean playAfterConnect,
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ import android.view.MotionEvent;
|
|||
import android.view.View;
|
||||
|
||||
import org.schabi.newpipe.util.Localization;
|
||||
import org.schabi.newpipe.util.image.PicassoHelper;
|
||||
import org.schabi.newpipe.util.ServiceHelper;
|
||||
import org.schabi.newpipe.util.image.CoilHelper;
|
||||
|
||||
public class PlayQueueItemBuilder {
|
||||
private static final String TAG = PlayQueueItemBuilder.class.toString();
|
||||
|
|
@ -33,7 +33,7 @@ public class PlayQueueItemBuilder {
|
|||
holder.itemDurationView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
PicassoHelper.loadThumbnail(item.getThumbnails()).into(holder.itemThumbnailView);
|
||||
CoilHelper.INSTANCE.loadThumbnail(holder.itemThumbnailView, item.getThumbnails());
|
||||
|
||||
holder.itemRoot.setOnClickListener(view -> {
|
||||
if (onItemClickListener != null) {
|
||||
|
|
|
|||
|
|
@ -13,8 +13,9 @@ import androidx.collection.SparseArrayCompat;
|
|||
|
||||
import com.google.common.base.Stopwatch;
|
||||
|
||||
import org.schabi.newpipe.App;
|
||||
import org.schabi.newpipe.extractor.stream.Frameset;
|
||||
import org.schabi.newpipe.util.image.PicassoHelper;
|
||||
import org.schabi.newpipe.util.image.CoilHelper;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
|
@ -207,8 +208,8 @@ public class SeekbarPreviewThumbnailHolder {
|
|||
Log.d(TAG, "Downloading bitmap for seekbarPreview from '" + url + "'");
|
||||
|
||||
// Gets the bitmap within the timeout of 15 seconds imposed by default by OkHttpClient
|
||||
// Ensure that your are not running on the main-Thread this will otherwise hang
|
||||
final Bitmap bitmap = PicassoHelper.loadSeekbarThumbnailPreview(url).get();
|
||||
// Ensure that you are not running on the main thread, otherwise this will hang
|
||||
final var bitmap = CoilHelper.INSTANCE.loadBitmapBlocking(App.getInstance(), url);
|
||||
|
||||
if (sw != null) {
|
||||
Log.d(TAG, "Download of bitmap for seekbarPreview from '" + url + "' took "
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue