Я реализую ExoPlayer в RecyclerView. Но при прокрутке видео останавливается, а звук нет.
Как я могу выпустить ExoPlayer в RecyclerView? Или как я могу получить положение переработанного объекта, чтобы я мог выпустить ExoPlayer?
Это мой объект данных
public class enter code here Video {
private String url;
private Context context;
Boolean playWhenReady = false;
int currentWindow = 0;
long playbackPosition = 0;
ExoPlayer player;
public Video(String url, Context context) {
this.url = url;
this.context = context;
}
public void setCurrentWindow(int currentWindow) {
this.currentWindow = currentWindow;
}
public void setPlaybackPosition(long playbackPosition) {
this.playbackPosition = playbackPosition;
}
public void setPlayWhenReady(Boolean playWhenReady) {
this.playWhenReady = playWhenReady;
}
public void setPlayer(ExoPlayer player) {
this.player = player;
}
public ExoPlayer getPlayer() {
return player;
}
public String getUrl() {
return url;
}
public Context getContext() {
return context;
}
public Boolean getPlayWhenReady() {
return playWhenReady;
}
public int getCurrentWindow() {
return currentWindow;
}
public long getPlaybackPosition() {
return playbackPosition;
}
}
И это мой класс адаптера: Я пробовал это с помощью метода onViewRecycled (), но поскольку я не получаю позицию, я не могу отпустить плеер.
public class VideoAdapter extends RecyclerView.Adapter<VideoAdapter.ViewHolder> {
private ArrayList<Video> mDataset;
public static class ViewHolder extends RecyclerView.ViewHolder {
public PlayerView mExoPlayer;
public ViewHolder(View itemView) {
super(itemView);
mExoPlayer = itemView.findViewById(R.id.video_view);
}
}
public VideoAdapter(ArrayList<Video> myDataset) {
mDataset = myDataset;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View itemView=LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item, parent, false);
return new ViewHolder(itemView);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
initPlayer(holder,position);
}
private void initPlayer(ViewHolder holder,int position) {
mDataset.get(position).setPlayer(ExoPlayerFactory.newSimpleInstance(
new DefaultRenderersFactory(mDataset.get(position).getContext()),
new DefaultTrackSelector(), new DefaultLoadControl()));
holder.mExoPlayer.setPlayer(mDataset.get(position).getPlayer());
mDataset.get(position).getPlayer().setPlayWhenReady(mDataset.get(position).getPlayWhenReady());
mDataset.get(position).getPlayer().seekTo(mDataset.get(position).getCurrentWindow(), mDataset.get(position).getPlaybackPosition());
Uri uri = Uri.parse(mDataset.get(position).getUrl());
MediaSource mediaSource = buildMediaSource(uri);
mDataset.get(position).getPlayer().prepare(mediaSource, true, false);
}
private MediaSource buildMediaSource(Uri uri) {
return new ExtractorMediaSource.Factory(
new DefaultHttpDataSourceFactory("exoplayer-codelab")).
createMediaSource(uri);
}
@Override
public int getItemCount() {
return mDataset.size();
}
@Override
public void onViewRecycled(@NonNull ViewHolder holder) {
super.onViewRecycled(holder);
}
}
Я создал новый проект, который может помочь всем, кто пытается это сделать: github.com/paulo-coutinho/rvplayer
Я думаю, что было бы проще выпустить плеер, когда его вид переработан.
Класс адаптера:
@Override
public void onViewRecycled(@NonNull ViewHolder holder) {
int position = holder.getAdapterPosition();
if (mDataset.get(position) != null) {
mDataset.get(position).getPlayer().release();
}
super.onViewRecycled(holder);
}
Если вы используете проигрыватель release(), его нельзя будет использовать снова, поэтому это не очень хорошая идея, если вы планируете повторно использовать проигрыватель в переработанном виде.
@ChristopherPerry Как потом выпустить плеер и восстановить его?
@Arjun Вы должны сохранить единственный экземпляр проигрывателя в родительском Activity / Fragment, создавая экземпляр проигрывателя внутри метода onResume() и выпуская проигрыватель внутри метода onStop(). Здесь - официальная демонстрация, которая реализует это. У него есть куча других вещей, но особенно посмотрите на MainActivity.java и PlayerManager.java.
Кроме того, Кристофер Перри был прав, когда они заявили, что плеер нельзя использовать после релиза.
Система не может содержать несколько экземпляров ExoPlayer. Может кинуть OOM Exception. Следовательно, вы должны выпустить ExoPlayer, когда пользователь не видит элемент. В этом случае я предлагаю вам использовать описанный ниже метод из RecyclerView.Adapter.
override fun onViewDetachedFromWindow(holder: ViewHolder) {
holder.itemView.player?.stop()
holder.itemView.player?.release()
holder.itemView.player = null
super.onViewDetachedFromWindow(holder)
}
И затем в классе ViewHolder вы должны проверить, если player == null, вы должны его инициализировать.
holder.yourplayername.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View v) {
}
@Override
public void onViewDetachedFromWindow(View v) {
holder.yourplayername.getPlayer().stop();
}
});
Привет. Надеюсь, этот код будет полезен для вас, потому что работает для меня.
спасибо, отлично сработало!
он останавливает видео, но если ваше видео на половине экрана все еще воспроизводится после остановки видео на экране снова, вы хотите воспроизвести его, показывайте пустым? что это за решение этого
Не могли бы вы поделиться полным кодом, как я могу использовать exo player в режиме ресайклера.