停止Exoplayer onSwipe of ViewPager

时间:2017-10-11 09:15:18

标签: java android android-viewpager exoplayer

我正在使用$role = Role::where("display_name",'=', $request->route("role"))->first(); $role->delete() //fails $role->forceDelete() //also fails 单片段实例,其中我正在显示ViewPager文件,如图片,视频,音频。

我已经实施Media来处理ExoPlayer& Video个文件。并Audio用于图片。

this来避免内存泄漏我在Glide中发布ExoPlayer这样的对象:

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(); } 我正在初始化视图:

onViewCreated()

我正在使用 @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); } } 。这是FragmentStatePagerAdapeter方法:

getItem

我无法在@Override public Fragment getItem(int position) { return ItemViewerFragment.newInstance(mItems.get(position)); } 的第一次扫描中检测到片段的onPause。在第二次滑动Viewpager文件停止播放时。

在活动中,我尝试添加video/audio

.addOnPageChangeListener

@Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { try { ((ItemViewerFragment)mAdapter.getItem(mPreviousPos)).imHiddenNow(); } catch (Exception e) { e.printStackTrace(); } mPreviousPos = position; }

ItemViewerFragment.java

仍然public void imHiddenNow(){ releasePlayer(); } 继续比赛。

这是Screencast的Video Link

Demo project GitHub link

请注意,下方发布的解决方案不起作用

5 个答案:

答案 0 :(得分:3)

以下是寻呼机适配器的代码:

 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);
    }
}

这是滚动侦​​听器:

  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) {

        }
    });

对于媒体,您可以使用for循环并立即将所有片段添加到列表中,然后使用它来提高效率:

viewPager.setOffscreenPageLimit(3);

这将确保只有3个片段实例可用,这足够了。

对于使用单个片段,我建议你这样做:

 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;
}

然后在onCreate of Fragment中你可以像这样检索你的文件:

File file;
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    file = getArguments().getSerializable("file");

}

现在将您的片段添加到寻呼机中,如下所示:

 for (int i = 0; i < totalFiles; i++) {
            viewPagerAdapter.addFragment(MyFragment.newInstance(fileList.get(i));
        }

希望这有帮助。

答案 1 :(得分:2)

我遵循了一种在HashMap内维护PagerAdapter片段对象的方法

  1. 声明一个接口:
interface FragmentLifecycle {
    void onPauseFragment()
}
  1. 在Fragment中实现接口。
public void onPauseFragment() {
    if (simpleExoPlayer != null){
        simpleExoPlayer.setPlayWhenReady(false);
    }
}
  1. 将所有片段对象存储在HashMap<Integer,Fragment>中,并以相应的位置作为键。在PagerAdapter中声明哈希图。还声明一种getter方法,用于从hashmap访问片段对象。例如

    @Override
    public Fragment getItem(int position) {
        ItemViewerFragment fragment = ItemViewerFragment.newInstance(mItems.get(position));
        mFragments.put(position,fragment);
        return fragment;
    }
    

    public ItemViewerFragment getMapItem(int position){       返回mFragments.get(position);     }

  2. 在声明了viewPager的活动中,保留一个变量currentPosition并实现ViewPager.OnPageChangeListener

  3. 内部onPageSelected方法中,

        @Override
        public void onPageSelected(int position) {
            if(mAdapter.getMapItem(currentPosition) != null) (mAdapter.getMapItem(currentPosition)).onPauseFragment();
            currentPosition = position;
        }
    

答案 2 :(得分:1)

自从我使用Exoplayer&amp; amp;我有点解决了类似的问题。请注意,API已经发生了一些变化,因此请使用以下代码来了解如何实现潜在的解决方案。如果它不起作用,请告诉我,我会进一步研究API并回复您。

来到解决方案:

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 );
}

答案 3 :(得分:1)

问题在于,在ViewPager中更改片段可见性时,不会调用onPauseonResume。 解决方案是添加2个可见性事件:losingVisibilitygainVisibility

为什么这是一个很好的解决方案?

因为您保持框架管理Fragment缓存和生命周期。 我们只需要在片段中添加暂停和恢复媒体所需的回调。

分步操作:

以下代码仅是我的代码的解释。检查Step*.java类以查看完整的实现。

  1. YourFragment.java中创建losingVisibilitygainVisibility方法:

    public class YourFragment extends Fragment {
    
        /**
          * This method is only used by viewpager because the viewpager doesn't call onPause after
          * changing the fragment
          */
        public void losingVisibility() {
            // IMPLEMENT YOUR PAUSE CODE HERE
            savePlayerState();
            releasePlayer();
        }
    
        /**
          * This method is only used by viewpager because the viewpager doesn't call onPause after
          * changing the fragment
        */
        public void gainVisibility() {
            // IMPLEMENT YOUR RESUME CODE HERE
            loadVideo();
        }
    }
    
  2. 每次在YourActivity.java中选择一个新页面(losingVisibility)时,调用gainVisibilityonPageSelected

    mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        }
    
        @Override
        public void onPageSelected(int position) {
            YourFragment cachedFragmentLeaving = mYourPagerAdapter.getCachedItem(mCurrentItem);
            if (cachedFragmentLeaving != null) {
                cachedFragmentLeaving.losingVisibility();
            }
            mCurrentItem = position;
            YourFragment cachedFragmentEntering = mYourPagerAdapter.getCachedItem(mCurrentItem);
            if (cachedFragmentEntering != null) {
                cachedFragmentEntering.gainVisibility();
            }
        }
    
        @Override
        public void onPageScrollStateChanged(int state) {
        }
    });
    
  3. getCachedItem添加到YourPagerAdapter.java

  

第三步是添加一种方法来检索缓存的片段。为此,我们必须缓存对创建的片段的引用(覆盖instantiateItem)并释放相同的引用(覆盖destroyItem)。

    public class YourPagerAdapter extends FragmentStatePagerAdapter {

            private SparseArray<YourFragment> mFragmentsHolded = new SparseArray<>();


        @NonNull
        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            Object fragment = super.instantiateItem(container, position);
            if(fragment instanceof StepFragment) {
                mFragmentsHolded.append(position, (StepFragment) fragment);
            }
            return fragment;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            mFragmentsHolded.delete(position);
            super.destroyItem(container, position, object);
        }

        public YourFragment getCachedItem(int position) {
            return mFragmentsHolded.get(position, null);
        }
    }

答案 4 :(得分:0)

我知道这么晚但我希望它可以帮助任何人...
viewPager保持屏幕外片段开始..
所以你有:
prev屏外片段(开始) - &gt;可见片段(工作) - &gt;下一个屏幕外片段(开始)
解决方案是你可以覆盖Fragment.setUserVisibleHint()并处理播放/暂停视频..