开发者

Listview with two different layouts

开发者 https://www.devze.com 2023-03-08 20:44 出处:网络
The application crashes after a few seconds of scrolling in the listview. String[] names = new String[] {\"Cook\",\"2/Person/15/5\",\"Cashier\",\"2/Person/15/5\"};

The application crashes after a few seconds of scrolling in the listview.

 String[] names = new String[] {"Cook","2/Person/15/5","Cashier","2/Person/15/5"};
 @Override
 public View getView(int position, View convertView, ViewGroup parent) {


        ViewHolder holder;
        View rowView = convertView;
        LayoutInflater inflater =(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        String[] info = names.get(position).split("/");

        if (rowView == 开发者_StackOverflow社区null) {

                if (info.length != 1) {
                    rowView = inflater.inflate(R.layout.employee, null, true);
                    holder = new ViewHolder();
                    holder.name = (TextView) rowView.findViewById(R.id.name);
                    holder.money= (TextView) rowView.findViewById(R.id.money);
                    holder.rating = (RatingBar) rowView.findViewById(R.id.rating);
                    rowView.setTag(holder);
                }else{
                    rowView = inflater.inflate(R.layout.lable, null, true);
                    holder = new ViewHolder();
                    holder.lable = (TextView) rowView.findViewById(R.id.name);

                    rowView.setTag(holder);
                }


            }

        holder = (ViewHolder) rowView.getTag();


        if (holder.lable==null) {
            holder.name.setText(info[1]);
            holder.money.setText(info[2]);
            holder.rating.setRating(Float.valueOf("1"));
        }else{
            holder.lable.setText(names.get(position));
        }

        //}



        return rowView;
    }


Since you are using a the Viewholder-pattern and recycle views, you end up with jumble. This is because you have two different kind of views in your list, and when you get a convertview, it will be one of those views.

Imagine a dataset A with layout/view a, and same for B b

(-B- means it is not shown on screen yet) So if your initial list is Aa, Bb, Bb, Aa, -B- , -B- and you scroll to bring data B into the list.. Then you will get a convertview with layout a OR layout b , thus having no way to use the convertview reliably.

I am doing some searching to find a way to support different views in a ListView and at the same time use the convertView/viewHolder-pattern.. So far I have found this one to be interesting: https://github.com/commonsguy/cwac-merge#readme

What you want to do is to override the getItemViewType (position) . Here is an example. You of course have your dataTypes instead of MoreResultsLoader and YPContact .

@Override
public int getItemViewType(int position) {

    if (resultsList.get(position) instanceof MoreResultsLoader) {
        return VIEW_TYPE_MORE_RESULTS_LOADER;
    }
    if (resultsList.get(position) instanceof YPContact) {
        YPContact ypCon = (YPContact) resultsList.get(position);
        if(checkForGold(ypCon))
            return VIEW_TYPE_YPCONTACT_GOLD;
        else
            return VIEW_TYPE_YPCONTACT_REG;
    }
  }

Then in getView , you would need to check which view type you are dealing with and inflate/populate with the correct ViewHolder class.

public View getView(final int position, View convertView, ViewGroup parent) {

    View ourView = convertView;
    int itemViewType = getItemViewType(position);
    switch (itemViewType) {
    case VIEW_TYPE_MORE_RESULTS_LOADER:
        MoreResultsViewHolder moreResVH = null;
        if (ourView == null) {

            ourView = layoutInflator.inflate(R.layout.load_more_items,
                    null, true);
            moreResVH = new MoreResultsViewHolder(ourView);
            ourView.setTag(moreResVH);

        } else {
            moreResVH = (MoreResultsViewHolder) ourView.getTag();
        }
        if (moreResVH != null) {
            moreResVH.populate((MoreResultsLoader) resultsList
                    .get(position), context);
        }
        return ourView;
    case VIEW_TYPE_YPCONTACT_GOLD:
        ContactViewHolderGold contactVHGold = null;
        if (ourView == null) {

            ourView = layoutInflator.inflate(
                    R.layout.yp_search_result_list_item_gold, null, true);
            contactVHGold = new ContactViewHolderGold(ourView);
            ourView.setTag(contactVHGold);

        } else {
            contactVHGold = (ContactViewHolderGold) ourView.getTag();
        }
        if (contactVHGold != null) {
            final YPContact ypContact = (YPContact) resultsList
                    .get(position);
            contactVHGold.populate(ypContact, mCurrentLocation,
                    ypSearchResultsActivity);
            // moreResVH.populate(
            // (MoreResultsLoader)resultsList.get(position),context);
        }
        return ourView;


Android has a debug tool called logcat in ddms perspective where you will find the logs. You would be able to figure it out exactly the line number where the code crashes.

The convertView is primarily used when all the list items are uniform. As it helps in recycling the views. Here we are not sure if the recycled view is a R.layout.employee or R.layout.lable. This might be causing the problem.

Again thats the guess. The logcat will help you narrow down the problem.


Look at the first item "Cook":

String[] names = new String[] {"Cook","2/Person/15/5","Cashier","2/Person/15/5"};

You're doing:

String[] info = names.get(position).split("/");

And then:

holder.name.setText(info[1]);
holder.money.setText(info[2]);

I don't have to look into logcat to see ArrayIndexOutOfBoundsException

0

精彩评论

暂无评论...
验证码 换一张
取 消