带有自定义适配器的 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。这样你就可以只处理一个集合,并轻松检索和更改位置

的项目的 属性