BottomSheet结合ViewPager出现ArrayIndexOutOfBoundsException异常
解决ViewPager滑动时的ArrayIndexOutOfBoundsException异常
我看到你在开发带ViewPager标签栏的BottomSheet时遇到了滑动几次就抛出数组越界的问题,咱们直接从错误根源和解决方案说起:
问题根源分析
从Logcat的报错信息可以定位到异常发生在Bottom_Viewpager_Fragment.onCreateView方法的第47行,也就是遍历liquerdata数组的循环里。
核心问题在于你把i和j定义成了Fragment的成员变量,而非循环内部的局部变量:
- ViewPager默认会预加载相邻的Fragment,当你滑动三四次后,新的Fragment实例被创建时,
i和j并没有被重置为0,而是继承了之前Fragment实例中已经累加后的数值(比如第一次循环后i和j会变成5)。 - 而你的
liquertype和price数组长度都是5,最大索引为4,这时候再执行liquertype[i]或price[j],就会直接触发ArrayIndexOutOfBoundsException。
解决方案
有两种简单的修复方式,推荐第一种:
方法1:将i、j改为循环局部变量(推荐)
把i和j移到onCreateView方法内部,作为循环的局部变量,这样每次创建Fragment时都会重新初始化:
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { view = inflater.inflate(R.layout.fragment_bottom__viewpager_, container, false); bottle_checked1 = (AppCompatImageView)view.findViewById(R.id.bottle_checked1); bottle_text1 = (CustomTextView)view.findViewById(R.id.bottle_text1); beerprice1 = (CustomTextView)view.findViewById(R.id.beerprice1); liquer_data_providers = new ArrayList<>(); // 将i、j改为局部变量,每次onCreateView都会重新初始化 int i = 0; int j = 0; for(String data:liquerdata) { liquer_data_provider = new Liquer_Data_Provider(liquertype[i],data,price[j]); i++; j++; liquer_data_providers.add(liquer_data_provider); bottle_text1.setText(liquer_data_provider.getGlass_name()); beerprice1.setText(Integer.toString(liquer_data_provider.getPrice())); } bottle_text1.setOnClickListener(this); return view; }
方法2:每次onCreateView时重置成员变量
如果一定要保留i、j作为成员变量,在进入onCreateView时手动把它们重置为0:
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { view = inflater.inflate(R.layout.fragment_bottom__viewpager_, container, false); bottle_checked1 = (AppCompatImageView)view.findViewById(R.id.bottle_checked1); bottle_text1 = (CustomTextView)view.findViewById(R.id.bottle_text1); beerprice1 = (CustomTextView)view.findViewById(R.id.beerprice1); liquer_data_providers = new ArrayList<>(); // 重置成员变量i和j为0 i = 0; j = 0; for(String data:liquerdata) { liquer_data_provider = new Liquer_Data_Provider(liquertype[i],data,price[j]); i++; j++; liquer_data_providers.add(liquer_data_provider); bottle_text1.setText(liquer_data_provider.getGlass_name()); beerprice1.setText(Integer.toString(liquer_data_provider.getPrice())); } bottle_text1.setOnClickListener(this); return view; }
额外小提示
你在循环里每次都给bottle_text1和beerprice1设置文本,最终只会显示最后一条数据的内容,这大概率不是你想要的效果。如果要展示所有的酒类数据,建议用RecyclerView或ListView来渲染整个liquer_data_providers列表,而不是重复覆盖同一个TextView的内容。
内容的提问来源于stack exchange,提问作者user9550968
相关产品推荐
相关产品推荐

