关于ViewPager2内存泄露问题

关于ViewPager2内存泄露问题

师兄告诉我ViewPager2和RadioGroup联动发生内存泄露 本文记录debug过程

我使用的是ViewPager2和RadioGroup联动 以下为代码

private void initView(){
    ArrayList<Fragment> fragmentList = new ArrayList<>();
    //仓控单元
    fragmentList.add(new CabinetControlFragment());
    //检测单元
    fragmentList.add(new CabinetCheckFragment());
    //充电单元
    fragmentList.add(new ChargeFragment());
    //系统配置
    fragmentList.add(new SystemConfigFragment());
    //系统日志
    fragmentList.add(SystemLogFragment.newInstance());


    //以下 ViewPager2和RadioGroup 联动代码
    // 设置垂直滑动
    viewPager2.setOrientation(ViewPager2.ORIENTATION_VERTICAL);
    radioGroupTab.setOnCheckedChangeListener((group, checkedId) -> {
        if (checkedId == R.id.device_control_unit) {
            viewPager2.setCurrentItem(0);
        } else if (checkedId == R.id.device_check_unit) {
            viewPager2.setCurrentItem(1);
        }else if (checkedId == R.id.device_charge_unit) {
            viewPager2.setCurrentItem(2);
        }else if (checkedId == R.id.device_system_config) {
            viewPager2.setCurrentItem(3);
        }else if (checkedId == R.id.device_system_log) {
            viewPager2.setCurrentItem(4);
        }else if (checkedId == R.id.device_back_homepage) {
            //返回首页操作
            finish();
        }else{
            ToastUtil.show(this,"未知的 view");
        }
    });

    viewPager2.setAdapter(new FragmentStateAdapter(this){
        @Override
        public int getItemCount() {
            return fragmentList.size();
        }
        @NonNull
        @Override
        public Fragment createFragment(int position) {
            return fragmentList.get(position);
        }
    });
    //不让他上下滚动了
    viewPager2.setUserInputEnabled(false);
}

Android Studio自带的Profiler监视内存

过程

image-20220331161532224

在点击到ViewPager2和RadioGroup联动界面 快速点击切换发现内存泄露

image-20220331161906399

点击到references

image-20220331162137418

写的很清楚 在我写的Activity中fragment下标为4,被引用,导致无法释放

image-20220331162716427

解决

思路

我使用 fragmentList 创建所有的界面的方法比较耗内存的,而且会导致内存泄露,故应该使用动态创建方式。

使用一个List<Class>存储所有的界面的class,再用classnewInstance()创建界面。

这方面也可以使用Class.forName(“com.my.app.xxx”);使用String数组保存class name的反射,但是感觉不如第一个方便。

但是还需要指定 viewPager2.setOffscreenPageLimit(1); 原因如下

setOffscreenPageLimit的作用建议看一下这个博主写的。

ViewPager.setOffscreenPageLimit()的一些记录_daoxiaomianzi的博客-CSDN博客

最后实现代码(删除了一些没改动的代码)

private void initView()  {
    List<Class> fragmentList = new ArrayList<>();
    //仓控单元
    fragmentList.add(CabinetControlFragment.class);
    //检测单元
    fragmentList.add(CabinetCheckFragment.class);
    //充电单元
    fragmentList.add(ChargeFragment.class);
    //系统配置
    fragmentList.add(SystemConfigFragment.class);
    //系统日志
    fragmentList.add(SystemLogFragment.class);

    viewPager2.setAdapter(new FragmentStateAdapter(this){
        @Override
        public int getItemCount() {
            return fragmentList.size();
        }
        @NonNull
        @Override
        public Fragment createFragment(int position) {
            try {
                return (Fragment) fragmentList.get(position).newInstance();
            } catch (Exception e) {
                e.printStackTrace();
                return new Fragment();
            }
        }
    });
    //不让他上下滚动了
    viewPager2.setUserInputEnabled(false);
    //防止内存泄露
    viewPager2.setOffscreenPageLimit(1);
}

使用profiler调试结果

image-20220331175011451

已正常。Good Job!

有参数写法

突然想起来我的是没有参数的,有参数的写法就是需要获取constructor,所以,你应该写一个统一样的构造器,不一样也可用if判断,具体代码如下

Constructor con = fragmentList.get(position).getConstructor(String.class);
        return (Fragment) con.newInstance("新界面");
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值