我正在像 Instagram 一样实现 Timeline,但我有多个选项卡,正如我在图片中提到的那样。每个选项卡都有单独的片段。每个片段都有一个用于多个 Post 的 RecyclerView,我为渲染列表制作了一个适配器。我在适配器中传递了列表,每个帖子项目可以有多个图像和视频,所以我在 single_post_item 中制作了另一个 RecyclerView 并制作了另一个用于渲染帖子媒体的适配器。我在第一个适配器中为多个帖子制作了一个 View Holder,然后我从该 ViewHolder 调用了另一个适配器。在 Post Media Adapter 中,我制作了两个视图支架,一个用于图像,另一个用于视频。我使用 Exo Player 播放视频。无法解决的问题是,如果我在两个连续的帖子项目中有视频,它会为这两个项目播放视频。那么我该如何处理这种情况。期待各位大大的回复。提前致谢
AllStoriesFragment.java
public class AllStoriesFragment extends DaggerFragment implements OnStoryFetchListener {
private HomeActivity activity;
private FragmentAllStoriesBinding binding;
private List<StoriesResponse> storiesResponseList=new ArrayList<>();
private AllStoriesAdapter adapter;
private List<MediaAttachment> mediaAttachments=new ArrayList<>();
@Inject
StoriesRepository storiesRepository;
private List<Stories> allStoriesList = new ArrayList<>();
private List<StoriesMediaItems> storiesMediaItems=new ArrayList<>();
private Boolean scrollToTop = false;
@Inject
TTViewModelFactory viewModelFactory;
StoriesViewModel storiesViewModel;
private LinearLayoutManager linearLayoutManager;
@Override
public void onAttach(Context context) {
super.onAttach(context);
activity = (HomeActivity) context;
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_all_stories, container, false);
return binding.getRoot();
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
storiesViewModel= ViewModelProviders.of(this, viewModelFactory).get(StoriesViewModel.class);
storiesViewModel.getLatestAllStories(0, AllStoriesFragment.this);
storiesViewModel.getAllStories().observe(this,stories -> {
if (storiesResponseList == null || adapter == null) {
setAdapter();
}
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new StoriesDiffCallback(allStoriesList, stories));
diffResult.dispatchUpdatesTo(adapter);
storiesResponseList.clear();
allStoriesList.clear();
//allStoriesList.addAll(stories != null ? stories : new ArrayList<>());
allStoriesList = stories;
for (int i=0;i<allStoriesList.size();i++){
storiesMediaItems = storiesViewModel.getAllStoryMedia(allStoriesList.get(i).getId());
storiesResponseList.add(new StoriesResponse(allStoriesList.get(i).getPostedBy(),allStoriesList.get(i).getPostedByName(),allStoriesList.get(i).getId(),allStoriesList.get(i).getLikesCount(),allStoriesList.get(i).getCommentsCount(),allStoriesList.get(i).getShareCount(),allStoriesList.get(i).getTimeStamp(),allStoriesList.get(i).getLiked(),storiesMediaItems));
}
if(adapter == null){
setAdapter();
}
else {
adapter.notifyDataSetChanged();
}
if (scrollToTop) {
if (storiesResponseList.size() > 0) {
binding.allStoriesListView.scrollToPosition(0);
}
scrollToTop = false;
}
});
}
private void setAdapter(){
if (storiesResponseList == null) {
this.storiesResponseList = new ArrayList<>();
}
linearLayoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false);
binding.allStoriesListView.setLayoutManager(linearLayoutManager);
binding.allStoriesListView.setItemViewCacheSize(0);
adapter= new AllStoriesAdapter(activity,activity,getChildFragmentManager(),storiesResponseList,storiesRepository);
binding.allStoriesListView.setAdapter(adapter);
}
@Override
public void onStoryFetched(boolean asc) {
scrollToTop = asc;
if (binding.swiperefresh != null && binding.swiperefresh.isRefreshing()) {
binding.swiperefresh.setRefreshing(false);
}
binding.fetchStoriesProgress.setVisibility(View.GONE);
}
@Override
public void onPause() {
super.onPause();
if(adapter!=null) {
StoriesViewHolder view = (StoriesViewHolder) binding.allStoriesListView.findViewHolderForAdapterPosition(adapter.getPosition());
if (view != null && view.adapter.player!=null) {
view.adapter.player.setPlayWhenReady(false);
}
}
}
@Override
public void onResume() {
super.onResume();
if(adapter!=null) {
StoriesViewHolder view = (StoriesViewHolder) binding.allStoriesListView.findViewHolderForAdapterPosition(adapter.getPosition());
if (view != null && view.adapter.player!=null) {
view.adapter.player.setPlayWhenReady(true);
}
}
}
@Override
public void onDestroy() {
//storiesRepository.deleteAllStoryAndStoryMedia();
if(adapter!=null) {
StoriesViewHolder view = (StoriesViewHolder) binding.allStoriesListView.findViewHolderForAdapterPosition(adapter.getPosition());
if (view != null && view.adapter.player!=null) {
view.adapter.releasePlayer();
}
}
storiesResponseList.clear();
if (adapter != null) {
adapter.notifyDataSetChanged();
}
linearLayoutManager = null;
scrollToTop = false;
storiesViewModel = null;
super.onDestroy();
}
}
AllStoriesAdapter.java
public class AllStoriesAdapter extends RecyclerView.Adapter<StoriesViewHolder> {
private Context context;
private List<StoriesResponse> storiesResponseList;
private HomeActivity activity;
private FragmentManager fragmentManager;
private int position;
public AllStoriesAdapter(HomeActivity activity, Context context, FragmentManager manager, List<StoriesResponse> storiesResponseList, StoriesRepository storiesRepository) {
this.context = context;
this.storiesResponseList = storiesResponseList;
this.activity = activity;
this.fragmentManager = manager;
}
@NonNull
@Override
public StoriesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
StoriesItemLayoutBinding itemBinding = StoriesItemLayoutBinding.inflate(layoutInflater, parent, false);
return new StoriesViewHolder(itemBinding);
}
@Override
public void onBindViewHolder(@NonNull final StoriesViewHolder holder, final int position) {
holder.bind(storiesResponseList.get(position), this, fragmentManager, activity);
}
}
@Override
public int getItemCount() {
return storiesResponseList.size();
}
public int getPosition() {
return position;
}
public void setPosition(int position) {
this.position = position;
}
/*@Override
public void onViewDetachedFromWindow(@NonNull StoriesViewHolder holder) {
super.onViewDetachedFromWindow(holder);
holder.binding.moreOptions.setOnClickListener(null);
if(holder.adapter!=null) {
holder.adapter.releasePlayer();
}
}*/
@Override
public void onViewRecycled(StoriesViewHolder holder) {
super.onViewRecycled(holder);
if(holder.adapter!=null) {
holder.adapter.releasePlayer();
}
}
public StoriesResponse getLastItemInList() {
return storiesResponseList.get(storiesResponseList.size() - 1);
}
}
StoriesViewHolder.java
public class StoriesViewHolder extends RecyclerView.ViewHolder{
public StoriesItemLayoutBinding binding;
public int dotsCount;
//private StoriesMediaPagerAdapter adapter;
public StoriesMediaRecyclerViewAdapter adapter;
private ArrayList<ImageView> dots;
private Context context;
private List<StoriesMediaItems> storyItemsList = new ArrayList<>();
public StoriesViewHolder(StoriesItemLayoutBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
public void bind(StoriesResponse response, AllStoriesAdapter adapter, FragmentManager manager, HomeActivity activity) {
binding.setStories(response);
binding.setAdapter(adapter);
binding.executePendingBindings();
context = activity;
setUpStoriesAttachmentPager(response.getList(),activity,manager);
}
private void setUpStoriesAttachmentPager(List<StoriesMediaItems> storyItems, HomeActivity activity,FragmentManager manager) {
this.storyItemsList = storyItems == null ? new ArrayList<>() : storyItems;
binding.storiesItemPager.setLayoutManager(new LinearLayoutManager(activity, LinearLayoutManager.HORIZONTAL, false));
adapter = new StoriesMediaRecyclerViewAdapter(activity, storyItemsList, false);
binding.storiesItemPager.setAdapter(adapter);
binding.storiesItemPager.setItemViewCacheSize(0);
SnapHelper snapHelper = new PagerSnapHelper();
binding.storiesItemPager.setOnFlingListener(null);
snapHelper.attachToRecyclerView(binding.storiesItemPager);
binding.dotsContainer.attachToRecyclerView(binding.storiesItemPager, snapHelper);
if (storyItemsList.size() == 1) {
binding.dotsContainer.setVisibility(View.GONE);
} else {
binding.dotsContainer.setVisibility(View.VISIBLE);
}
}
}
StoriesMediaRecyclerViewAdapter.java
public class StoriesMediaRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int TYPE_IMAGE = 1, TYPE_VIDEO = 2;
private List<StoriesMediaItems> storiesMediaItemsList;
private Context context;
private String tag = "";
Boolean isFromComment = false;
private SimpleExoPlayer player;
private DefaultTrackSelector trackSelector;
private SimpleExoPlayerView simpleExoPlayerView;
private MediaSource mediaSource;
private DefaultExtractorsFactory extractorsFactory;
private DataSource.Factory mediaDataSourceFactory;
private int position = -1;
public StoriesMediaRecyclerViewAdapter(Context context, List<StoriesMediaItems> storiesMediaItemsList,Boolean isFromComment) {
this.context = context;
this.storiesMediaItemsList = storiesMediaItemsList;
this.tag = tag;
this.isFromComment = isFromComment;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
if (viewType == TYPE_IMAGE) {
StoriesImageViewBinding itemBinding = StoriesImageViewBinding.inflate(layoutInflater, parent, false);
return new ImageViewHolder(itemBinding);
} else {
StoriesVideoViewBinding itemBinding = StoriesVideoViewBinding.inflate(layoutInflater, parent, false);
return new VideoViewHolder(itemBinding);
}
}
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
StoriesMediaItems storiesMediaItems = storiesMediaItemsList.get(position);
if (holder instanceof ImageViewHolder) {
ImageViewHolder imageHolder = (ImageViewHolder) holder;
Log.d("StoriesTelloImageViewHolder","ImageViewHolder");
setPosition(holder.getAdapterPosition());
imageHolder.storiesImageViewBinding.captionView.setText(storiesMediaItems.getCaption());
imageHolder.storiesImageViewBinding.storiesImage.setImageURI(storiesMediaItems.getSourceUrl());
imageHolder.storiesImageViewBinding.storiesImage.setScaleType(ImageView.ScaleType.CENTER_CROP);
byte[] decodedString = Base64.decode(storiesMediaItems.getThumbImage(), Base64.DEFAULT);
Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
Drawable image = new BitmapDrawable(context.getResources(), decodedByte);
Glide.with(context)
.load(Uri.parse(storiesMediaItems.getSourceUrl()))
.apply(new RequestOptions().placeholder(image))
.dontAnimate()
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(imageHolder.storiesImageViewBinding.storiesImage);
imageHolder.storiesImageViewBinding.storiesImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(isFromComment) {
Intent intent = new Intent(context, StoriesImageViewerActivity.class);
intent.putExtra("storiesMedia", storiesMediaItems);
context.startActivity(intent);
}
else{
Intent intent = new Intent(context, StoriesCommentsActivity.class);
intent.putExtra("storyId", storiesMediaItemsList.get(position).getStoriesId());
intent.putExtra("Tag", storiesMediaItemsList.get(position).getTAG());
intent.putExtra("storyposition", position);
context.startActivity(intent);
}
}
});
} else {
VideoViewHolder videoHolder = (VideoViewHolder) holder;
Log.d("StoriesTelloVideoViewHolder","VideoViewHolder");
byte[] decodedString = Base64.decode(storiesMediaItemsList.get(holder.getAdapterPosition()).getThumbImage(), Base64.DEFAULT);
Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
Drawable image = new BitmapDrawable(context.getResources(), decodedByte);
Glide.with(context)
.load(image)
.dontAnimate()
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(videoHolder.itemBinding.videoPlayerThumbnail);
}
}
public class ImageViewHolder extends RecyclerView.ViewHolder {
StoriesImageViewBinding storiesImageViewBinding;
public ImageViewHolder(StoriesImageViewBinding binding) {
super(binding.getRoot());
this.storiesImageViewBinding = binding;
}
}
public class VideoViewHolder extends RecyclerView.ViewHolder {
StoriesVideoViewBinding itemBinding;
public VideoViewHolder(StoriesVideoViewBinding binding) {
super(binding.getRoot());
this.itemBinding = binding;
}
}
@Override
public int getItemViewType(int position) {
StoriesMediaItems storiesMediaItems = storiesMediaItemsList.get(position);
if (storiesMediaItems.getType().equalsIgnoreCase("image")) {
return TYPE_IMAGE;
} else {
return TYPE_VIDEO;
}
}
@Override
public int getItemCount() {
return storiesMediaItemsList.size();
}
public void initializeExoPlayer() {
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory =
new AdaptiveTrackSelection.Factory(bandwidthMeter);
trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
player = ExoPlayerFactory.newSimpleInstance(context, trackSelector);
extractorsFactory = new DefaultExtractorsFactory();
mediaDataSourceFactory = new DefaultDataSourceFactory(context, Util.getUserAgent(context, "TelloTalkStoriesPlayer"), (TransferListener<? super DataSource>) bandwidthMeter);
}
public void releasePlayer() {
if (player != null) {
player.stop();
player.release();
player = null;
trackSelector = null;
}
}
public MediaSource buildMediaSource(Uri uri, VideoViewHolder holder) {
mediaSource = new ExtractorMediaSource(uri,
mediaDataSourceFactory, extractorsFactory, null, null);
player.setPlayWhenReady(true);
player.prepare(mediaSource);
holder.itemBinding.videoPlayerView.setPlayer(player);
return mediaSource;
}
public int getPosition() {
return position;
}
public void setPosition(int position) {
this.position = position;
}
@Override
public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) {
super.onViewRecycled(holder);
Log.d("StoriesTelloOnViewRecycled","onViewRecycled");
//releasePlayer();
}
@Override
public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
Log.d("StoriesTelloOnAttachedToRecyclerView","onAttachedToRecyclerView");
}
@Override
public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) {
super.onDetachedFromRecyclerView(recyclerView);
Log.d("StoriesTelloOnDetachedFromRecyclerView","onDetachedFromRecyclerView");
//releasePlayer();
}
@Override
public void onViewAttachedToWindow(@NonNull RecyclerView.ViewHolder holder) {
super.onViewAttachedToWindow(holder);
Log.d("StoriesTelloOnViewAttachedToWindow","onViewAttachedToWindow");
if(holder instanceof ImageViewHolder){
releasePlayer();
}
else if(holder instanceof VideoViewHolder){
releasePlayer();
VideoViewHolder videoHolder = (VideoViewHolder) holder;
initializeExoPlayer();
setPosition(holder.getAdapterPosition());
byte[] decodedString = Base64.decode(storiesMediaItemsList.get(holder.getAdapterPosition()).getThumbImage(), Base64.DEFAULT);
Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
Drawable image = new BitmapDrawable(context.getResources(), decodedByte);
Glide.with(context)
.load(image)
.dontAnimate()
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(videoHolder.itemBinding.videoPlayerThumbnail);
buildMediaSource(Uri.parse(storiesMediaItemsList.get(holder.getAdapterPosition()).getSourceUrl()), (VideoViewHolder) holder);
player.addListener(new Player.EventListener() {
@Override
public void onTimelineChanged(Timeline timeline, Object manifest, int reason) {
}
@Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
}
@Override
public void onLoadingChanged(boolean isLoading) {
if(isLoading){
((VideoViewHolder) holder).itemBinding.videoPlayerProgressbar.setVisibility(View.VISIBLE);
}
else
{
((VideoViewHolder) holder).itemBinding.videoPlayerProgressbar.setVisibility(View.GONE);
}
}
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
switch (playbackState)
{
case Player.STATE_BUFFERING:
((VideoViewHolder) holder).itemBinding.videoPlayerProgressbar.setVisibility(View.VISIBLE);
break;
case Player.STATE_ENDED:
((VideoViewHolder) holder).itemBinding.videoPlayerThumbnail.setVisibility(View.VISIBLE);
break;
case Player.STATE_IDLE:
//if (ivPlayPause != null) {
// ivPlayPause.setVisibility(View.VISIBLE);
//}
// if (player != null) {
// player.seekTo(0);
// player.setPlayWhenReady(true);
// }
//ivPlayPause.setImageResource(R.drawable.video_play);
//isPlay = false;
break;
case Player.STATE_READY:
((VideoViewHolder) holder).itemBinding.videoPlayerProgressbar.setVisibility(View.GONE);
((VideoViewHolder) holder).itemBinding.videoPlayerThumbnail.setVisibility(View.GONE);
//ivThumbnail.setVisibility(View.GONE);
//progressBar.setVisibility(View.GONE);
//handler.postDelayed(runnable, 1000);
break;
default:
break;
}
}
@Override
public void onRepeatModeChanged(int repeatMode) {
}
@Override
public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
}
@Override
public void onPlayerError(ExoPlaybackException error) {
}
@Override
public void onPositionDiscontinuity(int reason) {
}
@Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
}
@Override
public void onSeekProcessed() {
}
});
}
}
@Override
public void onViewDetachedFromWindow(@NonNull RecyclerView.ViewHolder holder) {
super.onViewDetachedFromWindow(holder);
Log.d("StoriesTelloOnViewDetachedFromWindow","onViewDetachedFromWindow");
}
}