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
并在那里设置断点,但是当对话框被关闭时,断点永远不会被调用,onPause
或 onDetach
.
也不会被调用
这是否也意味着 ExoPlayer
实例在关闭对话框时仍然存在?
如何在关闭对话框时停止视频的音频?
我没有在另一个 Fragment 中使用 viewpager2,但根据 viewpager2 的文档和源代码,我认为你在从 Fragment 中创建适配器时不正确。
在class LightboxFragment
尝试换行
myViewPagerAdapter = new MyViewPagerAdapter(getActivity());
至
myViewPagerAdapter = new MyViewPagerAdapter(this);
Fragment: if the ViewPager2 lives directly in a Fragment subclass.
您正在使用它,就好像 Viewpager2 直接存在于主机中一样 activity。
这意味着您将 LightboxVideoFragment
放在与 LightboxFragment
相同的 FragmentManager 中,并且生命周期更改为 LightboxFragment
不会影响它的兄弟姐妹(不是 children 因为他们应该是)
如果您也查看构造函数的 viewpager2 的源代码
正确的构造函数通过 getChildFragmentManager()
和片段的生命周期将 viewpager2 适配器中的片段绑定到主机片段,而不是 Activity's
生命周期。
(我没有试验或测试过这些知识,也没有阅读过源代码)。
我有一个 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
并在那里设置断点,但是当对话框被关闭时,断点永远不会被调用,onPause
或 onDetach
.
这是否也意味着 ExoPlayer
实例在关闭对话框时仍然存在?
如何在关闭对话框时停止视频的音频?
我没有在另一个 Fragment 中使用 viewpager2,但根据 viewpager2 的文档和源代码,我认为你在从 Fragment 中创建适配器时不正确。
在class LightboxFragment
尝试换行
myViewPagerAdapter = new MyViewPagerAdapter(getActivity());
至
myViewPagerAdapter = new MyViewPagerAdapter(this);
Fragment: if the ViewPager2 lives directly in a Fragment subclass.
您正在使用它,就好像 Viewpager2 直接存在于主机中一样 activity。
这意味着您将 LightboxVideoFragment
放在与 LightboxFragment
相同的 FragmentManager 中,并且生命周期更改为 LightboxFragment
不会影响它的兄弟姐妹(不是 children 因为他们应该是)
如果您也查看构造函数的 viewpager2 的源代码
正确的构造函数通过 getChildFragmentManager()
和片段的生命周期将 viewpager2 适配器中的片段绑定到主机片段,而不是 Activity's
生命周期。
(我没有试验或测试过这些知识,也没有阅读过源代码)。