在视图页的滑动上停止 Exoplayer

2022-09-03 02:34:03

我正在使用一个带有单个片段的实例,其中我显示图像,视频,音频等文件。ViewPagerMedia

我已经实现了处理和文件。对于图像。ExoPlayerVideoAudioGlide

为了避免内存泄漏,我正在释放对象,如下所示:ExoPlayerItemViewerFragment.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);

        }
    }

我正在使用.这是方法:FragmentStatePagerAdapetergetItem

@Override
public Fragment getItem(int position) {
    return ItemViewerFragment.newInstance(mItems.get(position));
}

我无法在第一次滑动时检测到片段。第二次滑动时,文件将停止播放。onPauseViewpagervideo/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();
    }

仍然继续玩。video/audio

这是截屏视频的视频链接

演示项目 GitHub 链接


答案 1

我遵循了维护内部片段对象的方法HashMapPagerAdapter

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

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

  2. 在已声明保留一个变量并实现 的活动中。viewPagercurrentPositionViewPager.OnPageChangeListener

  3. 内部方法,onPageSelected

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

答案 2

从将来开始编辑:切勿将对 Fragment 实例的引用直接保存在 FragmentPagerAdapter 中,因为它可能会在进程死亡后导致崩溃。

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

 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 Loop 并一次将所有片段添加到列表中,然后使用它来提高效率:

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

希望这有帮助。


推荐