Android SecionList and Holder

社会主义新天地 提交于 2019-12-13 00:09:21

问题


I have list with section, but this ListView is very slow.

I need any holder, but i don't know how I can make it.

When I had one type of view it was simple, but here I have problem.

I create holder, but when ListView is showing, I see:

"titel","title","title","item","item"

"titel","title","title","item"

"titel","title","title","item","item","item"

This is my code:

public class EntryAdapter extends ArrayAdapter<Item> {

private ArrayList<Item> items;
private LayoutInflater vi;
Context context;
private String nazwa;

public EntryAdapter(Context context,ArrayList<Item> items, String nazwa) {
    super(context,0, items);
    this.items = items;
    this.context = context;
    this.nazwa = nazwa;
    vi = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

And my get View:

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

    final Item i = items.get(position);
    if (i != null) {
        if(i.isSection()){
            SectionItem si = (SectionItem)i;
            convertView = vi.inflate(R.layout.list_item_section, null);

            convertView.setOnClickListener(null);
            convertView.setOnLongClickListener(null);
            convertView.setLongClickable(false);

            final TextView sectionView = (TextView) convertView.findViewById(R.id.list_item_section_text);
        }else{
                Obiekt ei = (Obiekt)i;
                convertView = vi.inflate(R.layout.row_list, null);
                final TextView title = (TextView)convertView.findViewById(R.id.row_tytul);
                final TextView odleglosc = (TextView)convertView.findViewById(R.id.row_odleglosc);
                final ImageView obrazek = (ImageView)convertView.findViewById(R.id.row_ikona_mala);
                final LinearLayout pole = (LinearLayout)convertView.findViewById(R.id.LinearLayout1);

        }
    }
    return convertView;
}

回答1:


I have list with section, but this ListView is very slow.

You are always inflating a new view in your getView() method. Inflating a view, typically takes a long time.

You want to re-use previous views, by checking if the 'convertView' is null or not. This will increase the performance. NOTE, you also have to implement getItemViewType() and getViewTypeCount() since you have two different views:

public class MyAdapter extends ArrayAdapter<Item> {

    private List<Item> items;
    private int TYPE_SECTION = 0;
    private int TYPE_OBIEKT = 1;
    private static LayoutInflater vi;

    public MyAdapter(Context context, List<Item> _items) {
        super(context, 0);
        vi = (LayoutInflater) context.getSystemService(Service.LAYOUT_INFLATER_SERVICE);
        items = _items;
    }

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


    /**
     * @see android.widget.BaseAdapter#getViewTypeCount()
     * Determines how many different views you have
     */
    @Override
    public int getViewTypeCount() {
        return 2; // We have two different kinds of views
    }

    /**
     * @see android.widget.BaseAdapter#getItemViewType(int)
     */
    @Override
    public int getItemViewType(int position) {
        Item item = items.get(position);
        if (item.isSection())
            return TYPE_SECTION;

        return TYPE_OBIEKT;
    }

    /**
     * @see android.widget.ArrayAdapter#getView(int, android.view.View, android.view.ViewGroup)
     */
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        // Get the item
        final Item item = items.get(position);

        if (getItemViewType(position) == TYPE_SECTION) {

            // Return a SectionView object
            return getSectionView(position, convertView, parent, (SectionItem) item);
        }

        // Return an Obiekt object
        return getObiektView(position, convertView, parent, (Obiekt) item);
    }

    /**
     * SectionView specific
     * 
     * @param position
     * @param convertView
     * @param parent
     * @param item
     * @return
     */
    public View getSectionView(int position, View convertView, ViewGroup parent, SectionItem item) {

        SectionHolder holder;
        if(convertView == null){

            holder = new SectionHolder();

            // Inflate a new View
            convertView = vi.inflate(R.layout.list_item_section, null);
            holder.sectionView = (TextView) convertView.findViewById(R.id.list_item_section_text);

            // Set the ObiektHolder as the tag, to retrieve it for re-using
            convertView.setTag(holder);

        } else {
            holder = (SectionHolder) convertView.getTag();
        }

        // Holder is never null here
        holder.sectionView.setText(item.getSectionTitle());

        return convertView;

    }

    public View getObiektView(int position, View convertView, ViewGroup parent, Obiekt item) {

        ObiektHolder holder;
        if(convertView == null){

            holder = new ObiektHolder();

            // Inflate a new View
            convertView = vi.inflate(R.layout.row_list, null);
            holder.title = (TextView)convertView.findViewById(R.id.row_tytul);
            holder.odleglosc = (TextView)convertView.findViewById(R.id.row_odleglosc);
            holder.obrazek = (ImageView)convertView.findViewById(R.id.row_ikona_mala);
            holder.pole = (LinearLayout)convertView.findViewById(R.id.LinearLayout1);

            // Set the ObiektHolder as the tag, to retrieve it for re-using
            convertView.setTag(holder);

        } else {
            holder = (ObiektHolder) convertView.getTag();
        }

        // Holder is never null here
        holder.title.setText(item.getObiektTitle());

        return convertView;
    }

    private static class SectionHolder {
        TextView    sectionView;
    }

    private static class ObiektHolder {
        TextView        title;
        TextView        odleglosc;
        ImageView       obrazek;
        LinearLayout    pole;
    }
}

NOTE: Tested and working now!




回答2:


http://www.youtube.com/watch?v=wDBM6wVEO70. Talks about listview peformance with view holder.

http://developer.android.com/training/improving-layouts/smooth-scrolling.html. Have a look at the documentation in the link under the heading Hold View Objects in a View Holder

Stright from the documentation :

Your code might call findViewById() frequently during the scrolling of ListView, which can slow down performance. Even when the Adapter returns an inflated view for recycling, you still need to look up the elements and update them. A way around repeated use of findViewById() is to use the "view holder" design pattern.

Example of viewholder.

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
  // TODO Auto-generated method stub
   ViewHolder holder;

        if (convertView == null) {
                  convertView = mInflater.inflate(R.layout.list, null);
                  convertView.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.FILL_PARENT,
                          LayoutParams.WRAP_CONTENT));
                  // Creates a ViewHolder and store references to the two children views
                  // we want to bind data to.
                  holder = new ViewHolder();
                  holder.t1=(TextView) convertView.findViewById(R.id.textView1);
                  holder.t2 = (TextView) convertView.findViewById(R.id.textView2);
                  holder.t3 = (TextView) convertView.findViewById(R.id.textView3);

                  convertView.setTag(holder);
              } else {
                  // Get the ViewHolder back to get fast access to the TextView

                  holder = (ViewHolder) convertView.getTag();
              }
              holder.t1.setText("set text")
              holder.t2.setText("set text2");
              holder.t3.setText("set text3");
              return convertView;
  }
}


class ViewHolder
{
  TextView t1,t2,t3;
}



回答3:


First of all you have to check if convertView is already inflated. If it's already inflated you can recycle it and you don't have to inflate it again. That's where you gain performance.

Example:

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

    View itemView = null;

    // not inflated
    if (convertView == null) {
        LayoutInflater inflater = (LayoutInflater) parent.getContext()
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        itemView = inflater.inflate(R.layout.list_item_section, null);
    } 
    // already inflated
    else {
        itemView = convertView;
    }

    // get your textview's etc.

    return itemView;
}


来源:https://stackoverflow.com/questions/15497847/android-secionlist-and-holder

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!