首页 > 解决方案 > Recyclerview 中的 Exoplayer 带有图像和视频,如 instagram,但仅停止最后一个视频,其他视频在 android 中回压后仍在播放

问题描述

我尝试了所有 StackOverflow 答案和 youtube 解决方案,但找不到任何合适的东西,这就是我在其中发布我的问题的原因。

我想制作一个像 Instagram 这样的应用程序,我可以显示图像和视频,但问题是

  1. 当我在回收站视图中向上滑动时,所有视频都会自动播放,而不仅仅是单个显示的屏幕。
  2. 当我按下按钮时,只有最后一个视频停止,其他视频(音频)仍在后台播放,直到终止应用程序。

我想做的是。

  1. 一次播放单个视频,显示在缓存中的其他视频商店(如 TikTok)的屏幕上,然后在滑动后观看这些视频。

  2. 后按所有带音频的视频停止

  3. 带有静音/取消静音和双击监听器的 onclicklistener。

这是我的代码...

主要活动.class

public class MainActivity extends AppCompatActivity {
ActivityMainBinding mainBinding;
Toolbar toolbar;
String JSON_URl = "https://wasisoft.com/dev/index.php";
List<newsFeedModel> feedModels = new ArrayList<>();
newsFeedAdapter imageAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mainBinding = ActivityMainBinding.inflate(getLayoutInflater());
    setContentView(mainBinding.getRoot());
    toolbar = findViewById(R.id.mews_feed_toolbar);
    toolbar.setTitle("NewsFeed");
    toolbar.setTitleTextColor(Color.WHITE);
    showList();

}

void showList() {
    AndroidNetworking.get(JSON_URl)
            .setPriority(Priority.LOW)
            .build()
            .getAsJSONArray(new JSONArrayRequestListener() {
                @Override
                public void onResponse(JSONArray response) {
                    // do anything with response
                    if (response != null) {
                        for (int i = 0; i < response.length(); i++) {
                            try {
                                JSONObject object = response.getJSONObject(i);
                                newsFeedModel FeedModel = new newsFeedModel();
                                FeedModel.setTitleName(object.getString("account_name"));
                                FeedModel.setLike(object.getString("likes"));
                                FeedModel.setDescrption(object.getString("media_type"));
                                FeedModel.setVideo(object.getString("media"));
                                FeedModel.setViewImg(object.getString("media"));
                                feedModels.add(FeedModel);
                                String res = object.getString("media");
                                Log.d("TAG", "onResponse: " + res);

                            } catch (JSONException e) {
                                e.printStackTrace();
                            }
                        }
                        imageADD(feedModels);
                    } else {
                        Toast.makeText(MainActivity.this, "None ", Toast.LENGTH_SHORT).show();
                    }
                }

                @Override
                public void onError(ANError error) {
                    // handle error
                    Toast.makeText(MainActivity.this, "No Value " + error.getErrorBody(), Toast.LENGTH_SHORT).show();
                    Log.d("TAG", "onError: " + error);
                }
            });
}

void imageADD(List<newsFeedModel> feedModel) {
    imageAdapter = new newsFeedAdapter(this, feedModel, this::videoPlayBack);
    LinearLayoutManager manager = new LinearLayoutManager(this);
    manager.setSmoothScrollbarEnabled(true);
    imageAdapter.notifyDataSetChanged();
    mainBinding.newsFeedRecycler.setAdapter(imageAdapter);
    mainBinding.newsFeedRecycler.setHasFixedSize(true);
    mainBinding.newsFeedRecycler.setLayoutManager(manager);


}
void videoPlayBack(PlayerView player, Uri videoUrl,int position) {
    BandwidthMeter meter = new DefaultBandwidthMeter();
    TrackSelector track = new DefaultTrackSelector(
            new AdaptiveTrackSelection.Factory(meter)
    );
    imageAdapter.exoPlayer = ExoPlayerFactory.newSimpleInstance(this, track);
    DefaultHttpDataSourceFactory factory = new DefaultHttpDataSourceFactory("video");
    ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
    MediaSource mediaSource = new ExtractorMediaSource(videoUrl, factory, extractorsFactory, null, null);
    player.setPlayer(imageAdapter.exoPlayer);
    player.setKeepScreenOn(true);
    imageAdapter.exoPlayer.prepare(mediaSource);
    imageAdapter.exoPlayer.setPlayWhenReady(true);
    player.setUseController(true);

}

@Override
public void onDestroy() {
    imageAdapter.releasePlayer();
    super.onDestroy();
}

@Override
protected void onPause() {
    super.onPause();
    imageAdapter.pausePlayer();
}
}

适配器类

public class newsFeedAdapter extends RecyclerView.Adapter {
public static final int imageFeed = 0;
public static final int videoFeed = 1;
public SimpleExoPlayer exoPlayer;
Context context;
videoCallBack callBack;
List<newsFeedModel> feedModels;
videoNewsFeed videoNews;
newsFeedModel model;
String Json_Url = "https://wasisoft.com/dev/";

public newsFeedAdapter(Context context, List<newsFeedModel> feedModels, videoCallBack callBack) {
    this.context = context;
    this.feedModels = feedModels;
    this.callBack = callBack;
}

public newsFeedAdapter() {
}

@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    if (viewType == 0) {
        View view = LayoutInflater.from(context).inflate(R.layout.images_news_feed, parent, false);
        return new imageNewsFeed(view);
    } else {

        View view = LayoutInflater.from(context).inflate(R.layout.video_news_feed, parent, false);
        return new videoNewsFeed(view);
    }
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    if (holder.getItemViewType() == 0) {
        newsFeedModel feed = feedModels.get(position);
        imageNewsFeed imageNews = (imageNewsFeed) holder;

        Glide
                .with(context)
                .load(Json_Url + feed.getViewImg())
                .centerCrop()
                .into(imageNews.viewPager);
        Log.d("TAG", "onBindViewHolder: " + feed.getViewImg());

        imageNews.title.setText(feed.getTitleName());
        imageNews.likes.setText(feed.getLike());
        imageNews.description.setText(feed.getDescription());

    } else {

        model = feedModels.get(position);
        videoNews = (videoNewsFeed) holder;
        videoNews.videoLikes.setText(model.getLike());
        videoNews.videoTitle.setText(model.getTitleName());
        videoNews.videoDescription.setText(model.getDescription());
        callBack.onSuccessPlay(videoNews.videoView, Uri.parse(Json_Url + model.getVideo()), position);
    }
}

@Override
public int getItemViewType(int position) {
    if (feedModels.get(position).getDescription().contains("picture")) {
        return imageFeed;
    } else
        return videoFeed;
}

@Override
public int getItemCount() {
    return feedModels.size();
}


public void releasePlayer() {
    if (exoPlayer != null) {
        videoNews.videoView.setPlayer(null);
        exoPlayer.setPlayWhenReady(true);
        exoPlayer.getPlaybackState();
        exoPlayer.release();
        exoPlayer = null;
    }
}

public void pausePlayer() {
    if (exoPlayer != null) {
        videoNews.videoView.setPlayer(null);
        exoPlayer.setPlayWhenReady(false);
        exoPlayer.getPlaybackState();
    }
}



public static class imageNewsFeed extends RecyclerView.ViewHolder {
    ImageView dpImage, viewPager;
    TextView title, likes, description;

    public imageNewsFeed(@NonNull View itemView) {
        super(itemView);
        dpImage = itemView.findViewById(R.id.profile_image_images_news_feed);
        viewPager = itemView.findViewById(R.id.profile_image_viewPage_news_feed);
        title = itemView.findViewById(R.id.profile_image_name_news_feed);
        likes = itemView.findViewById(R.id.profile_image_like_count_news_feed);
        description = itemView.findViewById(R.id.profile_image_comments_news_feed);
    }
}

public static class videoNewsFeed extends RecyclerView.ViewHolder {
    public PlayerView videoView;
    TextView videoTitle, videoLikes, videoDescription;

    public videoNewsFeed(@NonNull View itemView) {
        super(itemView);
        videoView = itemView.findViewById(R.id.item_video_exoplayer);
        videoTitle = itemView.findViewById(R.id.profile_video_name_news_feed);
        videoLikes = itemView.findViewById(R.id.profile_video_like_count_news_feed);
        videoDescription = itemView.findViewById(R.id.profile_video_comments_news_feed);
    }
    }
    }

videoFeed.xml

   <?xml version="1.0" encoding="utf-8"?>
   <androidx.constraintlayout.widget.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="wrap_content">

   <de.hdodenhof.circleimageview.CircleImageView
    android:id="@+id/profile_video_image_news_feed"
    android:layout_width="@dimen/_40sdp"
    android:layout_height="@dimen/_40sdp"
    android:layout_margin="@dimen/_8sdp"
    android:src="@drawable/ic_profile"
    app:civ_border_color="@color/black"
    app:civ_border_width="@dimen/_1sdp"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<TextView
    android:id="@+id/profile_video_name_news_feed"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginStart="@dimen/_8sdp"
    android:text="@string/app_name"
    android:textColor="@color/black"
    android:textSize="@dimen/_12ssp"
    app:layout_constraintBottom_toBottomOf="@id/profile_video_image_news_feed"
    app:layout_constraintStart_toEndOf="@id/profile_video_image_news_feed"
    app:layout_constraintTop_toTopOf="@id/profile_video_image_news_feed" />


<FrameLayout
    android:id="@+id/profile_video_video_news_feed"
    android:layout_width="match_parent"
    android:layout_height="@dimen/_300sdp"
    android:layout_marginTop="@dimen/_8sdp"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@id/profile_video_image_news_feed">

    <com.google.android.exoplayer2.ui.PlayerView
        android:id="@+id/item_video_exoplayer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"

        app:layout_constraintTop_toTopOf="parent"
        app:resize_mode="fill"
        app:show_buffering="when_playing"
        app:surface_type="texture_view" />

    <!--  <ImageView
          android:id="@+id/img_vol"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_gravity="right|bottom"
          android:layout_margin="8dp"
          android:src="@drawable/ic_unmute" />-->
</FrameLayout>

<ImageView
    android:id="@+id/profile_video_like_news_feed"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginStart="@dimen/_12sdp"
    android:layout_marginTop="@dimen/_12sdp"
    android:src="@drawable/ic_like"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@id/profile_video_video_news_feed"
    app:tint="@color/black" />

<ImageView
    android:id="@+id/profile_video_message_news_feed"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginStart="@dimen/_12sdp"
    android:layout_marginTop="@dimen/_12sdp"
    android:rotation="290"
    android:src="@drawable/ic_message"
    app:layout_constraintStart_toEndOf="@id/profile_video_like_news_feed"
    app:layout_constraintTop_toBottomOf="@id/profile_video_video_news_feed" />

<ImageView
    android:id="@+id/profile_video_share_news_feed"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginStart="@dimen/_12sdp"
    android:layout_marginTop="@dimen/_12sdp"
    android:src="@drawable/ic_send"
    app:layout_constraintStart_toEndOf="@id/profile_video_message_news_feed"
    app:layout_constraintTop_toBottomOf="@id/profile_video_video_news_feed" />

<TextView
    android:id="@+id/profile_video_like_count_news_feed"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="@dimen/_8sdp"
    android:text="@string/profileCount"
    android:textColor="@color/black"
    android:textSize="@dimen/_11ssp"
    app:layout_constraintStart_toStartOf="@id/profile_video_like_news_feed"
    app:layout_constraintTop_toBottomOf="@id/profile_video_like_news_feed" />

<TextView
    android:id="@+id/profile_video_like_text_news_feed"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginStart="@dimen/_4sdp"
    android:text="@string/like"
    android:textColor="@color/black"
    android:textSize="@dimen/_11ssp"
    app:layout_constraintEnd_toEndOf="@id/profile_video_name_comment_news_feed"
    app:layout_constraintStart_toEndOf="@id/profile_video_like_count_news_feed"
    app:layout_constraintTop_toTopOf="@id/profile_video_like_count_news_feed" />

<TextView
    android:id="@+id/profile_video_name_comment_news_feed"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="@dimen/_4sdp"
    android:text="@string/app_name"
    android:textColor="@color/black"
    android:textSize="@dimen/_11ssp"
    android:textStyle="bold"
    app:layout_constraintStart_toStartOf="@id/profile_video_like_count_news_feed"
    app:layout_constraintTop_toBottomOf="@id/profile_video_like_count_news_feed" />

<TextView
    android:id="@+id/profile_video_comments_news_feed"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:ellipsize="end"
    android:ems="19"
    android:justificationMode="inter_word"
    android:maxLines="2"
    android:text="@string/dummy_text"
    android:textColor="@color/text_color"
    android:textSize="@dimen/_11ssp"
    android:textStyle="normal"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toEndOf="@id/profile_video_name_comment_news_feed"
    app:layout_constraintTop_toTopOf="@id/profile_video_name_comment_news_feed"
    tools:ignore="UnusedAttribute" />

   </androidx.constraintlayout.widget.ConstraintLayout>

标签: javaandroidandroid-recyclerviewexoplayer2.x

解决方案


从代码中,我的理解是,当您单击该项目时,视频播放方法中会出现一个回调。你在这里分配

 imageAdapter.exoPlayer = ExoPlayerFactory.newSimpleInstance(this, track);

因此,每次单击该项目时,它都会从工厂分配一个新实例exoplayer,当您按下时,它只会释放最后分配的 exoplayer。

前一个实例仍处于活动状态并正在播放。

因此,要么在分配新实例之前释放前一个实例,要么重用同一个实例。

void videoPlayBack(PlayerView player, Uri videoUrl,int position) {
    BandwidthMeter meter = new DefaultBandwidthMeter();
    TrackSelector track = new DefaultTrackSelector(
            new AdaptiveTrackSelection.Factory(meter)
    );
    imageAdapter.releasePlayer();
    imageAdapter.exoPlayer = ExoPlayerFactory.newSimpleInstance(this, track);

    DefaultHttpDataSourceFactory factory = new DefaultHttpDataSourceFactory("video");
    ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
    MediaSource mediaSource = new ExtractorMediaSource(videoUrl, factory, extractorsFactory, null, null);
    player.setPlayer(imageAdapter.exoPlayer);
    player.setKeepScreenOn(true);
    imageAdapter.exoPlayer.prepare(mediaSource);
    imageAdapter.exoPlayer.setPlayWhenReady(true);
    player.setUseController(true);

}

推荐阅读