关于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监视内存
过程
在点击到ViewPager2和RadioGroup联动界面 快速点击切换发现内存泄露
点击到references
写的很清楚 在我写的Activity中fragment下标为4,被引用,导致无法释放
解决
思路
我使用 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调试结果
已正常。Good Job!
有参数写法
突然想起来我的是没有参数的,有参数的写法就是需要获取constructor,所以,你应该写一个统一样的构造器,不一样也可用if判断,具体代码如下
Constructor con = fragmentList.get(position).getConstructor(String.class);
return (Fragment) con.newInstance("新界面");