Android fragments onDestroyView()上带有FragmentStateAdapter的ViewPager2中的片段泄漏

Android fragments onDestroyView()上带有FragmentStateAdapter的ViewPager2中的片段泄漏,android-fragments,view,memory-leaks,android-viewpager2,android-ondestroy,Android Fragments,View,Memory Leaks,Android Viewpager2,Android Ondestroy,仅供参考:问题很简短,但以防万一,我在结尾添加了更多可能相关的信息。 我需要一个无限滚动的ViewPager2,我想重用项目中的一个片段,因为它已经设计好了,调用已经在viewLifeCycle中建立好了。。 我还知道VP回收屏幕外的片段(显示片段的1个偏移位置),并且在任何给定时刻至少有3个片段,因此使用片段是一种选择 问题是,当转到第四页时,ViewPager2尝试删除第一个片段(如预期的那样),LeakCanary向我显示了这一点(最后显示了整个诊断): 诊断从不指向我的参考文献,只指向a

仅供参考:问题很简短,但以防万一,我在结尾添加了更多可能相关的信息。

我需要一个无限滚动的ViewPager2,我想重用项目中的一个片段,因为它已经设计好了,调用已经在viewLifeCycle中建立好了。。 我还知道VP回收屏幕外的片段(显示片段的1个偏移位置),并且在任何给定时刻至少有3个片段,因此使用片段是一种选择

问题是,当转到第四页时,ViewPager2尝试删除第一个片段(如预期的那样),LeakCanary向我显示了这一点(最后显示了整个诊断):

诊断从不指向我的参考文献,只指向android库参考文献。

在代码吼叫之前,我有更多的行,但我一直在修剪它们,直到保持最低限度,泄漏仍然存在

// ----- onViewCreated() ------

MyPagerAdapter mPa = new MyPagerAdapter(
                getChildFragmentManager(),
                getViewLifecycleOwner().getLifecycle()
        );

vp.setAdapter(mPa);
扩展FragmentStateAdapter的MyPagerAdapter.class:

 @NonNull
    @Override
    public Fragment createFragment(int position) {
        return new SearchPageFragment2();    //Test Fragment
    }

@Override
    public int getItemCount() {
        return 8;    //Test fixed number
    }
泄漏的碎片:

public class SearchPageFragment2 extends Fragment {
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return FragmentSearchPageBinding.inflate(inflater).getRoot();
    }
}
是什么导致内存泄漏

问题到此结束。 序言…

主视图(泄漏发生时显示的最远的片段)是一个BackbackEntry,我们从主片段导航到它,该视图包含一个包含应用程序主要信息的工具栏,下面的工具栏是该视图的主要内容,一个固定大小的ViewPager2,有3个片段,在第一个片段上。。。我创建的“可变框架布局”:

private final MutableFrameLayoutAdapter<ElementDBLoaderViewModel.FrameActions> adapter = new MutableFrameLayoutAdapter<>(
            this,    //Fragment owner
            this::getChildFragmentManager,    //FragmentManager supplier
            () -> ElementDBLoaderViewModel.FrameActions.initiating,    //initialValue
            action -> {    //Function<X, Fragment>
                switch (action) {
                    case crossed:
                        return new AddElementExpandedFragment();
                    case not_crossed:
                        return new AddElementFragment();
                    case explore:
                        return new MainDBPaginationFragment2();
                }
                return null;
            }
    );
该部件是防漏的,在不同情况下需要数小时的测试

该部件的主要“发动机”:

if (oldFragment != null) {

                    FragmentTransaction ft = stackFm.beginTransaction();

                    ft.remove(oldFragment);


                    addCommit(ft, newFragment);
                }
private void addCommit(FragmentTransaction ft, Fragment newFragment) {
        fragmentCreated.get().fragmentCreated(newFragment);    //stateless adapter interface reference
        ft.add(getId(), newFragment);
        ft.commit();
    }
其中,“stackFm”是在构造函数中使用
childFragmentManager.get()
(“
this::getChildFragmentManager
”)获得FragmentManager供应商的结果

if (oldFragment != null) {

                    FragmentTransaction ft = stackFm.beginTransaction();

                    ft.remove(oldFragment);


                    addCommit(ft, newFragment);
                }
private void addCommit(FragmentTransaction ft, Fragment newFragment) {
        fragmentCreated.get().fragmentCreated(newFragment);    //stateless adapter interface reference
        ft.add(getId(), newFragment);
        ft.commit();
    }

if (oldFragment != null) {

                    FragmentTransaction ft = stackFm.beginTransaction();

                    ft.remove(oldFragment);


                    addCommit(ft, newFragment);
                }
private void addCommit(FragmentTransaction ft, Fragment newFragment) {
        fragmentCreated.get().fragmentCreated(newFragment);    //stateless adapter interface reference
        ft.add(getId(), newFragment);
        ft.commit();
    }
这个想法是要有一个简单易用的组件,没有任何花哨和直截了当的东西

基本上,这个可变框架布局所在的固定大小的ViewPager2的第一页(片段)可以采用3个不同片段的形式(取决于数据库大小)

泄漏的ViewPager2位于
maindPaginationFragment2.class
内,但在到达maindPaginationFragment2片段之前,我们必须先查看
addelementExpandedFragment2.class

泄漏诊断(没有我的参考资料)