我有ViewHolder
个自定义BaseAdapter
来填充ListView
,其数据来源为ArrayList<HashMap<String,String>>
。我的用例涉及重新排序,追加和删除ListView
中的元素。我将列表视图元素存储在ViewHolder
中以便进行回收。我需要每次都致电notifyDataSetChanged()
更改ListView
。
public class MycustomAdapter extends BaseAdapter{
private ArrayList<HashMap<String,String>> datalist;
private LayoutInflater inflater;
public MycustomAdapter(Context context,ArrayList<HashMap<String,String>> list){
this.datalist = list;
this.inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
private static class ViewHolder{
int index;
TextView menuItemName;
TextView status;
TextView customIndicator;
Button multiPurposeButton;
Button rejectButton;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return this.datalist.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if(convertView == null){
convertView = inflater.inflate(R.layout.list_element,parent,false);
viewHolder = new ViewHolder();
// Setting menu-item name text-box in view holder.
viewHolder.menuItemName = (TextView)convertView.findViewById(R.id.item_name);
// Setting status text-box in view holder.
viewHolder.status = (TextView)convertView.findViewById(R.id.status);
// Setting custom-indicator text-box in view holder.
viewHolder.customIndicator = (TextView)convertView.findViewById(R.id.custom_indicator);
// Setting accept/finish button in view holder.
viewHolder.multiPurposeButton = (Button)convertView.findViewById(R.id.accept_button);
// Setting reject button in view holder
viewHolder.rejectButton = (Button) convertView.findViewById(R.id.reject_button);
// Setting positiopn of view holder
viewHolder.index = position;
// setting tag for view holder
convertView.setTag(viewHolder);
}
else{
viewHolder = (ViewHolder)convertView.getTag();
}
viewHolder.menuItemName.setText(datalist.get(position).get("itemname"));
viewHolder.status.setText(datalist.get(position).get("status"));
viewHolder.customIndicator.setText(datalist.get(position).get("orderid"));
viewHolder.multiPurposeButton.setText(datalist.get(position).get("buttontext"));
return convertView;
}
public ArrayList<HashMap<String,String>> getData(){
return this.datalist;
}
public void setData(ArrayList<HashMap<String,String>> datalist){
this.datalist = datalist;
}
}
以下是我在调用notifyDataSetChanged()修改ListView
时从列表中删除项目时获得的异常:
FATAL EXCEPTION: main
java.lang.IndexOutOfBoundsException: Invalid index 3, size is 3
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:251)
at java.util.ArrayList.get(ArrayList.java:304)
at com.sample.application.MycustomAdapter.getView(MycustomAdapter.java:96)
at android.widget.AbsListView.obtainView(AbsListView.java:2319)
at android.widget.ListView.makeAndAddView(ListView.java:1793)
at android.widget.ListView.fillDown(ListView.java:678)
at android.widget.ListView.fillGap(ListView.java:642)
at android.widget.AbsListView.trackMotionScroll(AbsListView.java:5489)
at android.widget.AbsListView.scrollIfNeeded(AbsListView.java:3310)
at android.widget.AbsListView.onTouchEvent(AbsListView.java:3654)
at android.view.View.dispatchTouchEvent(View.java:7143)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2238)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1935)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2244)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1949)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2244)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1949)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2244)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1949)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2244)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1949)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2244)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1949)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2244)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1949)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1938)
at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1392)
at android.app.Activity.dispatchTouchEvent(Activity.java:2408)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1886)
at android.view.View.dispatchPointerEvent(View.java:7323)
at android.view.ViewRootImpl.deliverPointerEvent(ViewRootImpl.java:3560)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:3490)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:4637)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:4597)
at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:4749)
at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:171)
at android.view.InputEventReceiver.nativeConsumeBatchedInputEvents(Native Method)
at android.view.InputEventReceiver.consumeBatchedInputEvents(InputEventReceiver.java:163)
at android.view.ViewRootImpl.doConsumeBatchedInput(ViewRootImpl.java:4717)
at android.view.ViewRootImpl$ConsumeBatchedInputRunnable.run(ViewRootImpl.java:4771)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:747)
at android.view.Choreographer.doCallbacks(Choreographer.java:567)
at android.view.Choreographer.doFrame(Choreographer.java:534)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:733)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:153)
at android.app.ActivityThread.main(ActivityThread.java:5000)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:821)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:584)
at dalvik.system.NativeStart.main(Native Method)
我已将此错误的原因确定为与ListView
的数据源大小相关。当数据源最初有10个元素,然后在删除项目后有9个元素时,我的理解是否正确ListView期望缺少的元素存在?这些行引用了IndexOutOfBoundsException
:
viewHolder.menuItemName.setText(datalist.get(position).get("menu_item_name"));
viewHolder.status.setText(datalist.get(position).get("status"));
viewHolder.customIndicator.setText(datalist.get(position).get("order_id"));
viewHolder.multiPurposeButton.setText(datalist.get(position).get("button_text"));
这里的问题是我修改的数据源中不存在第10个元素,并且没有要设置的数据。解决这个问题的好方法是什么?
答案 0 :(得分:1)
我认为问题出在getItem()和getItemId()方法上。像这样覆盖这些方法
@Override
public Object getItem(int position) {
return this.datalist.get(position);
}
@Override
public long getItemId(int position) {
return position;
}