带有自定义适配器的 ListView - 列表为空时出现 IndexOutOfBoundsException
ListView with Custom Adapter - IndexOutOfBoundsException when list is empty
我有一个 List
,我在其中存储了一些从服务器获取的字符串。我有一个用于 ListView
的自定义适配器。每个项目都有一个 TextView 和一个 Switch。
在 onCreate 方法中,列表将为空,从服务器接收数据后,我在适配器上调用 notifyDataSetChanged。
我的查询特定于 Switch(或类似情况下的 Checkbox)。请看下面的代码。我会尽力用引号来解释它。
public class DetailDOMActivity extends AppCompatActivity {
ListView listview;
DealofTheMonthAdapter mDealofTheMonthAdapter;
List<String> mTitles = new ArrayList<String>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail_dom);
....
....
// Clearing the List before getting values from server
mTitles.clear();
listview = (ListView) findViewById(R.id.listView);
// If i remove the below 2 lines,
// and add them after getting the data from server,
// everything works fine.
// My query here is, when the list is empty,
// and when getCount() in adapter returns 0,
// why is getView() being called?
// Is this the normal behaviour?
mDealofTheMonthAdapter = new DealofTheMonthAdapter(this);
listview.setAdapter(mDealofTheMonthAdapter);
// Gets Values from server and
// stores them in mTitles List.
// At the end notifyDataSetChanged()
// is called on the adapter
getDataFromServer();
}
private class DealofTheMonthAdapter extends BaseAdapter {
final Context context;
List<Boolean> mProgress = new ArrayList<Boolean>();
public DealofTheMonthAdapter(Context context) {
this.context = context;
mProgress.clear();
}
@Override
public int getCount() {
return mTitles.size();
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.item_detail_dom, null);
holder = new ViewHolder();
holder.mTextView = (TextView) convertView.findViewById(R.id.textView);
holder.mImageView = (ImageView) convertView.findViewById(R.id.imageView);
holder.mSwitch = (SwitchCompat) convertView.findViewById(R.id.switch_dom);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.mTextView.setText(mTitles.get(position));
holder.mSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked)
mProgress.set(position, true);
else
mProgress.set(position, false);
}
});
// IndexOutOfBoundsException at the below line
holder.mSwitch.setChecked(mProgress.get(position));
return convertView;
}
}
public static class ViewHolder {
TextView mTextView;
ImageView mImageView;
SwitchCompat mSwitch;
}
}
据我所知,将根据 getCount() 计算的 return 计数调用 getView()。因此,当列表为空时,它应该 return 0 并且因此不应调用 getView() 。
有人可以向我解释一下这种行为吗?如果您还需要什么,请告诉我。
Logcat:
java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
at java.util.ArrayList.get(ArrayList.java:308)
at com.xxx.xx.DetailDOMActivity$DealofTheMonthAdapter.getView(DetailDOMActivity.java:285)
at android.widget.AbsListView.obtainView(AbsListView.java:2346)
at android.widget.ListView.measureHeightOfChildren(ListView.java:1281)
IndexOutOfBoundsException
是由 mProgress
引起的,它是空的,而 mTitles
不是。处理 ListView
上的多个集合可能很棘手,因为您必须始终确保所有集合至少具有 getCount()
的大小。这当然是可能的,但很容易出错。您可以做的是将所有信息包装在模型 class 周围。例如。
public class MyModel {
public String name;
public boolean isChecked
}
并从 List<String> mTitles
更改为 List<MyModel> mTitles
。这样你就可以只处理一个集合,并轻松检索和更改位置
的项目的 属性
我有一个 List
,我在其中存储了一些从服务器获取的字符串。我有一个用于 ListView
的自定义适配器。每个项目都有一个 TextView 和一个 Switch。
在 onCreate 方法中,列表将为空,从服务器接收数据后,我在适配器上调用 notifyDataSetChanged。
我的查询特定于 Switch(或类似情况下的 Checkbox)。请看下面的代码。我会尽力用引号来解释它。
public class DetailDOMActivity extends AppCompatActivity {
ListView listview;
DealofTheMonthAdapter mDealofTheMonthAdapter;
List<String> mTitles = new ArrayList<String>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail_dom);
....
....
// Clearing the List before getting values from server
mTitles.clear();
listview = (ListView) findViewById(R.id.listView);
// If i remove the below 2 lines,
// and add them after getting the data from server,
// everything works fine.
// My query here is, when the list is empty,
// and when getCount() in adapter returns 0,
// why is getView() being called?
// Is this the normal behaviour?
mDealofTheMonthAdapter = new DealofTheMonthAdapter(this);
listview.setAdapter(mDealofTheMonthAdapter);
// Gets Values from server and
// stores them in mTitles List.
// At the end notifyDataSetChanged()
// is called on the adapter
getDataFromServer();
}
private class DealofTheMonthAdapter extends BaseAdapter {
final Context context;
List<Boolean> mProgress = new ArrayList<Boolean>();
public DealofTheMonthAdapter(Context context) {
this.context = context;
mProgress.clear();
}
@Override
public int getCount() {
return mTitles.size();
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.item_detail_dom, null);
holder = new ViewHolder();
holder.mTextView = (TextView) convertView.findViewById(R.id.textView);
holder.mImageView = (ImageView) convertView.findViewById(R.id.imageView);
holder.mSwitch = (SwitchCompat) convertView.findViewById(R.id.switch_dom);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.mTextView.setText(mTitles.get(position));
holder.mSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked)
mProgress.set(position, true);
else
mProgress.set(position, false);
}
});
// IndexOutOfBoundsException at the below line
holder.mSwitch.setChecked(mProgress.get(position));
return convertView;
}
}
public static class ViewHolder {
TextView mTextView;
ImageView mImageView;
SwitchCompat mSwitch;
}
}
据我所知,将根据 getCount() 计算的 return 计数调用 getView()。因此,当列表为空时,它应该 return 0 并且因此不应调用 getView() 。
有人可以向我解释一下这种行为吗?如果您还需要什么,请告诉我。
Logcat:
java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
at java.util.ArrayList.get(ArrayList.java:308)
at com.xxx.xx.DetailDOMActivity$DealofTheMonthAdapter.getView(DetailDOMActivity.java:285)
at android.widget.AbsListView.obtainView(AbsListView.java:2346)
at android.widget.ListView.measureHeightOfChildren(ListView.java:1281)
IndexOutOfBoundsException
是由 mProgress
引起的,它是空的,而 mTitles
不是。处理 ListView
上的多个集合可能很棘手,因为您必须始终确保所有集合至少具有 getCount()
的大小。这当然是可能的,但很容易出错。您可以做的是将所有信息包装在模型 class 周围。例如。
public class MyModel {
public String name;
public boolean isChecked
}
并从 List<String> mTitles
更改为 List<MyModel> mTitles
。这样你就可以只处理一个集合,并轻松检索和更改位置