Question

I am getting

IllegalArgumentException: Can't have a viewTypeCount < 1

for my listview some times. I know it is for the list.size(). But this does not happen frequently, only some times I get this error and application crashes. I din't get the solution for this yet, do any body know this?

Update: This is what I am getting

10-17 05:34:49.103: ERROR/AndroidRuntime(1683): FATAL EXCEPTION: main
10-17 05:34:49.103: ERROR/AndroidRuntime(1683): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.racontrs/com.racontrs.Racontours.City}: java.lang.IllegalArgumentException: Can't have a viewTypeCount < 1
10-17 05:34:49.103: ERROR/AndroidRuntime(1683):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1647)
10-17 05:34:49.103: ERROR/AndroidRuntime(1683):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
10-17 05:34:49.103: ERROR/AndroidRuntime(1683):     at android.app.ActivityThread.access$1500(ActivityThread.java:117)
10-17 05:34:49.103: ERROR/AndroidRuntime(1683):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
10-17 05:34:49.103: ERROR/AndroidRuntime(1683):     at android.os.Handler.dispatchMessage(Handler.java:99)
10-17 05:34:49.103: ERROR/AndroidRuntime(1683):     at android.os.Looper.loop(Looper.java:130)
10-17 05:34:49.103: ERROR/AndroidRuntime(1683):     at android.app.ActivityThread.main(ActivityThread.java:3683)
10-17 05:34:49.103: ERROR/AndroidRuntime(1683):     at java.lang.reflect.Method.invokeNative(Native Method)
10-17 05:34:49.103: ERROR/AndroidRuntime(1683):     at java.lang.reflect.Method.invoke(Method.java:507)
10-17 05:34:49.103: ERROR/AndroidRuntime(1683):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
10-17 05:34:49.103: ERROR/AndroidRuntime(1683):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
10-17 05:34:49.103: ERROR/AndroidRuntime(1683):     at dalvik.system.NativeStart.main(Native Method)
10-17 05:34:49.103: ERROR/AndroidRuntime(1683): Caused by: java.lang.IllegalArgumentException: Can't have a viewTypeCount < 1
10-17 05:34:49.103: ERROR/AndroidRuntime(1683):     at android.widget.AbsListView$RecycleBin.setViewTypeCount(AbsListView.java:4387)
10-17 05:34:49.103: ERROR/AndroidRuntime(1683):     at android.widget.ListView.setAdapter(ListView.java:460)
10-17 05:34:49.103: ERROR/AndroidRuntime(1683):     at com.racontrs.Racontours.City.onCreate(City.java:66)
10-17 05:34:49.103: ERROR/AndroidRuntime(1683):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
10-17 05:34:49.103: ERROR/AndroidRuntime(1683):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
10-17 05:34:49.103: ERROR/AndroidRuntime(1683):  
   ... 11 more

And for this line I am getting

objTourListAdapter = new TourListAdapter(tourList, this);

listView.setAdapter(objTourListAdapter); // getting this when I try to add the adapter

Inside TourListAdapter,

public class TourListAdapter extends BaseAdapter {

    protected static final Context TourListAdapter = null;

    private ArrayList<Tour> tourList;

    private OnClickListener clickListener;
    private LayoutInflater mInflater;
    ViewHolder holder;
    City city;

    public TourListAdapter(ArrayList<Tour> tourList, City city) {
        this.city = city;
        this.tourList = tourList;
        mInflater = LayoutInflater.from(city);
        clickListener = (OnClickListener) city;
    }

    @Override
    public int getViewTypeCount() {
        return tourList.size();
    }

    @Override
    public int getItemViewType(int position) {
        return position;
    }

    @Override
    public int getCount() {
        return this.tourList.size();
    }

    @Override
    public Object getItem(int position) {
        return this.tourList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.listbox, null);
            convertView.setOnClickListener(clickListener);

            holder = new ViewHolder();
            holder.view1 = (TextView) convertView.findViewById(R.id.listText);
            holder.desc = (TextView) convertView.findViewById(R.id.editText1);
            holder.index = (TextView) convertView.findViewById(R.id.index);
            holder.desc.setVisibility(View.GONE);
            holder.priceBtn = (Button) convertView.findViewById(R.id.prcBtn);
            holder.icon = (ImageView) convertView.findViewById(R.id.listIcon);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        holder.view1.setText((String) tourList.get(position).getObjtourName());
        holder.desc.setText((String) tourList.get(position).getDescription());

        holder.priceBtn.setText((String) tourList.get(position).getObjPrice());
        holder.priceBtn.setOnClickListener(clickListener);

        holder.index.setText(String.valueOf(position));

        holder.icon.setImageBitmap(BitmapFactory
                .decodeFile((RaconTours.PATH + RaconTours.city + File.separator
                        + tourList.get(position).getObjtourName()
                        + File.separator + tourList.get(position)
                        .getThumbnailImageName()).replace(" ", "_")));

        return convertView;
    }
}

This is my activity onCreate code

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.city);
    Bundle bundle = getIntent().getExtras();
    tourList = (ArrayList<Tour>) bundle.get("arrayTour");
    citytextView = (TextView) findViewById(R.id.tourcity);
    ImageButton btnBack = (ImageButton) findViewById(R.id.btnBack);
    btnBack.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            setResult(RESULT_OK);
            finish();
        }
    });
    btnMap = (ImageButton) findViewById(R.id.btnMap);
    btnMap.setOnClickListener(this);
    btnUt = (ImageButton) findViewById(R.id.utBtn);
    btnUt.setOnClickListener(this);
    // setting the City Name
    citytextView.setText(RaconTours.city);
    /**** Identifying a listView ****/
    ListView listView = (ListView) findViewById(R.id.tourList);
    /**** Creating a new List Adapter class for binding the values ****/
    objTourListAdapter = new TourListAdapter(tourList, this);
    listView.setAdapter(objTourListAdapter);
    listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
    metrics = getResources().getDisplayMetrics();
    float dpForIcon = 60f;
    heightIcon = (int) (metrics.density * dpForIcon + 0.5f);
    if (null != RaconTours.dialog) {
        RaconTours.dialog.dismiss();
    }
}
Was it helpful?

Solution

So I am not sure what you want to do, but understand that getViewTypeCount() is only called once when you call setAdapter on the list view. So if the list is null or empty at that point, your application will fail. The value returned here should be thought of as more of a constant.

ViewTypes are used in View Recycling. Basically by specifying it as the length of the list, you are saying that every entity in the list would not be able to reuse any other view that the others in the list have used. If this is really true then this behavior is fine, but the minimum value has to at all times be 1. Also this cannot change after calling setAdapter until you create a new adapter to be set on the list view with the new content (this is just hot the view recycler in lister adapter works).

I would assume you could get by with a viewtypeCount of 1 since all your objects are of the same type. So just don't override getItemViewType or getItemViewCount(). These default to 0 and 1 respectively which will suffice for the adapter code you posted and still make efficient use of the view recycler.

OTHER TIPS

getViewTypeCount() should return the number of different views your ListView contains. If all of items in your ListView are the same type, you should return 1.

This is wrong,

@Override
public int getViewTypeCount() {

    return tourList.size();

}

because when tourList.size() is zero, you will get this exception

Since you have only one "type" of list view item use this :

@Override
public int getViewTypeCount() {
    return 1;
}

I know it's an old question but anyone wandering here like i did can benefit. You see, i needed to use:

@Override
public int getViewTypeCount() {

    return tourList.size();

}

Because it was the only way my row data would maintain their position during scroll. But i faced the crashed issue at times. So i added something it to prevent crash and now i'm all good:

  @Override
    public int getViewTypeCount() {
        int count;
        if (mItems.size() > 0) {
            count = getCount();
        } else {
            count = 1;
        }
        return count;
    }

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top