ViewPager2 不破坏片段

ViewPager2 not destroying fragments

我有一个 DialogFragment 和一个 ViewPager2:

public class LightboxFragment extends DialogFragment {

    private ViewPager2 viewPager;

    private MyViewPagerAdapter myViewPagerAdapter;

    public static LightboxFragment newInstance() {
        LightboxFragment fragment = new LightboxFragment();

        return fragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_lightbox, container, false);

        viewPager = v.findViewById(R.id.viewPager);

        FrameLayout closeButtonContainer = v.findViewById(R.id.close_button_container);
        closeButtonContainer.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dismiss();
            }
        });

        myViewPagerAdapter = new MyViewPagerAdapter(getActivity());
        viewPager.setAdapter(myViewPagerAdapter);

        return v;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    public class MyViewPagerAdapter extends FragmentStateAdapter {

        public MyViewPagerAdapter(FragmentActivity fa) {
            super(fa);
        }

        @NonNull
        @Override
        public Fragment createFragment(int position) {
            LightboxVideoFragment fragment = new LightboxVideoFragment();
            return fragment;
        }

        @Override
        public int getItemCount() {
            return items.size();
        }

    }

}

我的 LightboxVideoFragment 看起来像这样:

public class LightboxVideoFragment extends Fragment {

    private SimpleExoPlayer exoPlayer;

    private PlayerView playerView;

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.slideshow_video, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        playerView = view.findViewById(R.id.player_view);

        MediaItem mediaItem = MediaItem.fromUri(media.getUrls().getMp4());
        exoPlayer = new SimpleExoPlayer.Builder(getContext()).build();
        exoPlayer.setRepeatMode(Player.REPEAT_MODE_ALL);
        playerView.setPlayer(exoPlayer);
        exoPlayer.setMediaItem(mediaItem);
        exoPlayer.prepare();
        exoPlayer.play();
    }

    @Override
    public void onResume() {
        super.onResume();

        if (exoPlayer != null) {
            exoPlayer.play();
        }
    }

    @Override
    public void onPause() {
        super.onPause();

        if (exoPlayer != null) {
            exoPlayer.pause();
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();

        if (exoPlayer != null) {
            exoPlayer.release();
        }
    }

}

我的问题是:当 DialogFragment 关闭时,片段视频中的音频仍在播放。为什么是这样?我试过在我的片段中添加 onDestroy 并在那里设置断点,但是当对话框被关闭时,断点永远不会被调用,onPauseonDetach.

也不会被调用

这是否也意味着 ExoPlayer 实例在关闭对话框时仍然存在?

如何在关闭对话框时停止视频的音频?

我没有在另一个 Fragment 中使用 viewpager2,但根据 viewpager2 的文档和源代码,我认为你在从 Fragment 中创建适配器时不正确。

class LightboxFragment尝试换行

myViewPagerAdapter = new MyViewPagerAdapter(getActivity());

myViewPagerAdapter = new MyViewPagerAdapter(this);

这是因为根据文档https://developer.android.com/reference/androidx/viewpager2/adapter/FragmentStateAdapter#FragmentStateAdapter(androidx.fragment.app.Fragment)

Fragment: if the ViewPager2 lives directly in a Fragment subclass.

您正在使用它,就好像 Viewpager2 直接存在于主机中一样 activity。

这意味着您将 LightboxVideoFragment 放在与 LightboxFragment 相同的 FragmentManager 中,并且生命周期更改为 LightboxFragment 不会影响它的兄弟姐妹(不是 children 因为他们应该是)

如果您也查看构造函数的 viewpager2 的源代码

https://android.googlesource.com/platform/frameworks/support/+/refs/heads/androidx-master-dev/viewpager2/viewpager2/src/main/java/androidx/viewpager2/adapter/FragmentStateAdapter.java#102

正确的构造函数通过 getChildFragmentManager() 和片段的生命周期将 viewpager2 适配器中的片段绑定到主机片段,而不是 Activity's 生命周期。

(我没有试验或测试过这些知识,也没有阅读过源代码)。