java - Detención de Exoplayer onSwipe of ViewPager
android android-viewpager (2)
Estoy usando un ViewPager
con instancia de fragmento único en el que estoy mostrando archivos de Media
como imágenes, videos, audio.
Implementé ExoPlayer
para manejar archivos de Video
y Audio
. Y Glide
por las imágenes.
A partir de esto, para evitar fugas de memoria, estoy liberando el objeto ExoPlayer
esta manera en 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();
}
Y en onViewCreated()
estoy inicializando una vista como esta:
@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);
}
}
Estoy usando FragmentStatePagerAdapeter
. Este es el método getItem
:
@Override
public Fragment getItem(int position) {
return ItemViewerFragment.newInstance(mItems.get(position));
}
No puedo detectar la onPause
del fragmento al primer deslizamiento de Viewpager
. En segundo deslizamiento, video/audio
archivos de video/audio
dejan de reproducirse.
En actividad, intenté agregar .addOnPageChangeListener
:
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
try {
((ItemViewerFragment)mAdapter.getItem(mPreviousPos)).imHiddenNow();
} catch (Exception e) {
e.printStackTrace();
}
mPreviousPos = position;
}
Y en ItemViewerFragment.java
:
public void imHiddenNow(){
releasePlayer();
}
El video/audio
sigue sonando.
Aquí hay un Video Link al Screencast.
Proyecto de demostración GitHub link .
Tenga en cuenta que la solución publicada a continuación no funciona .
Aquí está el código para el adaptador de buscapersonas:
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
@Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
@Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
@Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
Aquí está el oyente de desplazamiento:
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//Stop media here.
}
@Override
public void onPageSelected(int position) {
//Save your previous position here.
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
Para los medios puede usar un bucle for y agregar todos los fragmentos a la lista de una vez y luego usar esto para la eficiencia:
viewPager.setOffscreenPageLimit(3);
Esto asegurará que solo 3 instancias de tu fragmento estén disponibles, lo cual es suficiente.
Para usar un solo fragmento, te sugiero que lo hagas así:
public MyFragment() {
}
//This is to send a file to the fragment if you need it.
public static MyFragment newInstance(File file) {
MyFragment fragment = new MyFragment();
Bundle bundle = new Bundle();
bundle.putSerializable("file", file);
fragment.setArguments(bundle);
return fragment;
}
Luego en el onCreate of Fragment puedes recuperar tu archivo de esta manera:
File file;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
file = getArguments().getSerializable("file");
}
Ahora agrega tus fragmentos al buscapersonas de esta manera:
for (int i = 0; i < totalFiles; i++) {
viewPagerAdapter.addFragment(MyFragment.newInstance(fileList.get(i));
}
Espero que esto ayude.
Ha pasado más de un año desde que utilicé Exoplayer y me enfrenté a un problema similar. Tenga en cuenta que las API han cambiado un poco, así que tome el siguiente código solo para tener una idea de cómo implementar una posible solución. Por favor, avíseme si no funciona, investigaré más las API y le responderé.
Llegando a la solución:
private int mPlayerCurrentPosition;
private int getCurrentPlayerPosition() {
return mExoPlayer.getCurrentPosition();
}
// call this from onPause
private void releaseExoplayer() {
mPlayerCurrentPosition = getPlayerCurrentPosition();
mExoPlayer.setPlayWhenReady(false);
mExoPlayer.release(); // this will make the player object eligible for GC
}
private void resumePlaybackFromPreviousPosition(int prevPosition) {
mExoPlayer.seekTo(mPlayerCurrentPosition );
}