操作 ArrayAdapter 时出现 ArrayIndexOutOfBoundsException
ArrayIndexOutOfBoundsException when manipulating ArrayAdapter
长话短说:我有一个带有 customAdapter(称为 MathAdapter)的 listView。此适配器处理 CalculationModel 类型的 ArrayList。默认情况下,我的列表中有大约 15 个 CalculationModels,但是,在特殊情况下,我必须删除其中的大约 6 个。
因为我是 Android 开发的新手(我来自 iOS),我的第一个基本问题是:
通常在哪里操作ListData?在我的例子中,片段初始化适配器并传递我的数据列表。在我的应用程序的生命周期中,我操纵这个列表并调用 notifiyDataSetChanged。一切都按预期工作,我可以一次删除或添加 1 个 CalculationModel,没有任何问题。
删除6个CalculationModel时也没有问题,也可以正常工作。当我尝试使用以下错误日志重新插入它们时应用程序崩溃:
04-27 07:48:59.194 1766-1766/com.example.test E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.test, PID: 1766
java.lang.ArrayIndexOutOfBoundsException: length=11; index=11
at android.widget.AbsListView$RecycleBin.addScrapView(AbsListView.java:8271)
at android.widget.ListView.layoutChildren(ListView.java:1600)
at android.widget.AbsListView.onLayout(AbsListView.java:2528)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1677)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1531)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1440)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1677)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1531)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1440)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at com.example.test.TouchDisableView.onLayout(TouchDisableView.java:57)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2284)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2004)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1236)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6471)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:803)
at android.view.Choreographer.doCallbacks(Choreographer.java:603)
at android.view.Choreographer.doFrame(Choreographer.java:573)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:789)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5356)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at dalvik.system.NativeStart.main(Native Method)
澄清一下,我不是 Java 的新手,我发现 ArrayIndexOutOfBounds 是问题所在,但我不知道这是哪里发生的,因为我的列表和适配器中的项目数更高比 11(预期为 14)
代码:
List<CalculationModel> data;
List<CalculationModel> backupData = new ArrayList<>();
@Override
public void onResume() {
if (mathApp.isCleanPhase) {
removeNonClearData();
} else {
addNonClearData();
}
adapter.notifyDataSetChanged();
super.onResume();
}
public void removeNonClearData() {
if (backupData.size() > 0) return;
for (int i = 0; i < data.size(); i++) {
CalculationModel tmp = data.get(i);
String sName = tmp.getSName();
if (sName.equals("r") || sName.equals("wv") || sName.equals("qv") || sName.equals("tw") || sName.equals("ti") || sName.equals("h") || sName.equals("rs")) {
backupData.add(data.remove(i));
i--;
}
}
adapter.itemCount = data.size();
}
public void addNonClearData() {
if (backupData.size() == 0) return;
for (int i = 0; i < backupData.size(); i++) {
//'r' is a default parameter, which shall be in row 6
if (backupData.get(i).getSName().equals("r")) data.add(5, backupData.remove(i));
else data.add(backupData.remove(i));
}
adapter.itemCount = data.size();
print(data.size());
}
编辑:忘了说,数据基本上是按照我想要的方式加载的,但是当我在我的列表中再次向上滚动时,应用程序崩溃了。所有数据都在我想在那里看到的列表中,但是当向上滚动时,--> 崩溃。
如前所述,我只是不明白这个错误是从哪里来的,因为日志没有提供任何相关信息...
when you are removing data from array call notifyDataSetChanged();
经过很长一段时间(基本上是最后 2 天)的挫折和困惑,我终于理解了 ListViews 的适配器是如何工作的(至少我希望如此)。
如问题中所述,我有以下设置:
包含数据列表的片段,以及在初始化时获取此数据列表的适配器。
现在,适配器在处理数据时有两种不同的行为。
如果只是编辑列表中的一个对象(例如,我想更改位置 4 上我的 CalculationModel 的参数 "value",一切正常,并且可以使用 notifyDataSetChanged() 接受更改。
如果从列表中删除一个完整的对象,notifyDataSetChanged() 也会正常工作并完成预期的工作。
但是,如果要将新对象添加到列表中(或者在我的情况下,重新插入已删除的对象),则有必要重新创建整个适配器,因为 notifyDataSetChanged() 不再起作用.
感谢您的帮助,如果没有评论中的输入,我可能无法完成。
长话短说:我有一个带有 customAdapter(称为 MathAdapter)的 listView。此适配器处理 CalculationModel 类型的 ArrayList。默认情况下,我的列表中有大约 15 个 CalculationModels,但是,在特殊情况下,我必须删除其中的大约 6 个。
因为我是 Android 开发的新手(我来自 iOS),我的第一个基本问题是:
通常在哪里操作ListData?在我的例子中,片段初始化适配器并传递我的数据列表。在我的应用程序的生命周期中,我操纵这个列表并调用 notifiyDataSetChanged。一切都按预期工作,我可以一次删除或添加 1 个 CalculationModel,没有任何问题。
删除6个CalculationModel时也没有问题,也可以正常工作。当我尝试使用以下错误日志重新插入它们时应用程序崩溃:
04-27 07:48:59.194 1766-1766/com.example.test E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.test, PID: 1766
java.lang.ArrayIndexOutOfBoundsException: length=11; index=11
at android.widget.AbsListView$RecycleBin.addScrapView(AbsListView.java:8271)
at android.widget.ListView.layoutChildren(ListView.java:1600)
at android.widget.AbsListView.onLayout(AbsListView.java:2528)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1677)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1531)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1440)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1677)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1531)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1440)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at com.example.test.TouchDisableView.onLayout(TouchDisableView.java:57)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2284)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2004)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1236)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6471)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:803)
at android.view.Choreographer.doCallbacks(Choreographer.java:603)
at android.view.Choreographer.doFrame(Choreographer.java:573)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:789)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5356)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at dalvik.system.NativeStart.main(Native Method)
澄清一下,我不是 Java 的新手,我发现 ArrayIndexOutOfBounds 是问题所在,但我不知道这是哪里发生的,因为我的列表和适配器中的项目数更高比 11(预期为 14)
代码:
List<CalculationModel> data;
List<CalculationModel> backupData = new ArrayList<>();
@Override
public void onResume() {
if (mathApp.isCleanPhase) {
removeNonClearData();
} else {
addNonClearData();
}
adapter.notifyDataSetChanged();
super.onResume();
}
public void removeNonClearData() {
if (backupData.size() > 0) return;
for (int i = 0; i < data.size(); i++) {
CalculationModel tmp = data.get(i);
String sName = tmp.getSName();
if (sName.equals("r") || sName.equals("wv") || sName.equals("qv") || sName.equals("tw") || sName.equals("ti") || sName.equals("h") || sName.equals("rs")) {
backupData.add(data.remove(i));
i--;
}
}
adapter.itemCount = data.size();
}
public void addNonClearData() {
if (backupData.size() == 0) return;
for (int i = 0; i < backupData.size(); i++) {
//'r' is a default parameter, which shall be in row 6
if (backupData.get(i).getSName().equals("r")) data.add(5, backupData.remove(i));
else data.add(backupData.remove(i));
}
adapter.itemCount = data.size();
print(data.size());
}
编辑:忘了说,数据基本上是按照我想要的方式加载的,但是当我在我的列表中再次向上滚动时,应用程序崩溃了。所有数据都在我想在那里看到的列表中,但是当向上滚动时,--> 崩溃。
如前所述,我只是不明白这个错误是从哪里来的,因为日志没有提供任何相关信息...
when you are removing data from array call notifyDataSetChanged();
经过很长一段时间(基本上是最后 2 天)的挫折和困惑,我终于理解了 ListViews 的适配器是如何工作的(至少我希望如此)。
如问题中所述,我有以下设置: 包含数据列表的片段,以及在初始化时获取此数据列表的适配器。
现在,适配器在处理数据时有两种不同的行为。
如果只是编辑列表中的一个对象(例如,我想更改位置 4 上我的 CalculationModel 的参数 "value",一切正常,并且可以使用 notifyDataSetChanged() 接受更改。
如果从列表中删除一个完整的对象,notifyDataSetChanged() 也会正常工作并完成预期的工作。
但是,如果要将新对象添加到列表中(或者在我的情况下,重新插入已删除的对象),则有必要重新创建整个适配器,因为 notifyDataSetChanged() 不再起作用.
感谢您的帮助,如果没有评论中的输入,我可能无法完成。