I am using a ViewPager
with single fragment instance in which I am showing Media
files like Images, Videos, Audio.
I have implemented ExoPlayer
for handling Video
& Audio
files. And Glide
for images.
To avoid the memory leaks I am releasing the ExoPlayer
object like this in ItemViewerFragment.java
:
private void releasePlayer() {
if (player != null) {
player.release();
player = null;
trackSelector = null;
simpleExoPlayerView.setPlayer(null);
}
}
@Override
public void onStart() {
super.onStart();
if (player == null && currentGalleryModel != null) {
initializePlayer();
}
}
@Override
public void onResume() {
super.onResume();
if (player == null && currentGalleryModel != null) {
initializePlayer();
}
}
@Override
public void onPause() {
super.onPause();
releasePlayer();
}
@Override
public void onStop() {
super.onStop();
releasePlayer();
}
And in onViewCreated()
I am initializing view like this :
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (currentGalleryModel.isVideo() || currentGalleryModel.isAudio()) {
simpleExoPlayerView.setVisibility(View.VISIBLE);
imageView.setVisibility(View.GONE);
initializePlayer();
} else if (currentGalleryModel.isImage() || currentGalleryModel.isGif()) {
simpleExoPlayerView.setVisibility(View.GONE);
imageView.setVisibility(View.VISIBLE);
Glide.with(this)
.load(currentGalleryModel.getFilePath())
.placeholder(android.R.color.black)
.fitCenter()
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(imageView);
}
}
I am using FragmentStatePagerAdapeter
. This is the getItem
method :
@Override
public Fragment getItem(int position) {
return ItemViewerFragment.newInstance(mItems.get(position));
}
I am not able to detect the onPause
of the fragment on first swipe of Viewpager
. On second swipe video/audio
files are stopped playing.
In activity I have tried adding .addOnPageChangeListener
:
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
try {
((ItemViewerFragment)mAdapter.getItem(mPreviousPos)).imHiddenNow();
} catch (Exception e) {
e.printStackTrace();
}
mPreviousPos = position;
}
And in ItemViewerFragment.java
:
public void imHiddenNow(){
releasePlayer();
}
Still video/audio
keeps on playing.
Here is a Video Link to the Screencast.
I followed an approach of maintaining HashMap
of fragment objects inside PagerAdapter
interface FragmentLifecycle {
void onPauseFragment()
}
public void onPauseFragment() {
if (simpleExoPlayer != null){
simpleExoPlayer.setPlayWhenReady(false);
}
}
Store all the fragment objects in a HashMap<Integer,Fragment>
with there respective positions as a key. Declare hashmap inside PagerAdapter
. Also declare one getter method for accessing fragment objects from hashmap. e.g.
@Override
public Fragment getItem(int position) {
ItemViewerFragment fragment = ItemViewerFragment.newInstance(mItems.get(position));
mFragments.put(position,fragment);
return fragment;
}
public ItemViewerFragment getMapItem(int position) { return mFragments.get(position); }
In activity where you have declared viewPager
keep one variable currentPosition
and implement ViewPager.OnPageChangeListener
.
Inside onPageSelected
method,
@Override
public void onPageSelected(int position) {
if(mAdapter.getMapItem(currentPosition) != null) (mAdapter.getMapItem(currentPosition)).onPauseFragment();
currentPosition = position;
}