Android - 可扩展ListView - 使用ViewHolder进行优化

Ano*_*ous 6 android expandablelistview expandablelistadapter

我有一个ListView,其中每一行都是图像+文本.我已使用ViewHolder将此列表实现为单独的列表以优化滚动.现在我尝试使用相同的视觉效果,但这次是Expandable ListView的一部分.我这样做,虽然在视觉上它看起来一样,但自然滚动是粘性的...所以问题是:

如何在Expandable ListView中使用ViewHolder技术?

我想必须在getChildView()方法中完成某些事情,但是我没有足够的经验来使用这种技术来弄清楚我自己的细节.这是适配器和子布局.任何帮助将不胜感激 !!

 public class MyExpandableListAdapter2 extends BaseExpandableListAdapter {



  private final SparseArray<Group> groups;
  public LayoutInflater inflater;
  public Activity activity;

  public MyExpandableListAdapter2(Activity act, SparseArray<Group> groups) {
    activity = act;
    this.groups = groups;
    inflater = act.getLayoutInflater();
  }

  @Override
  public Object getChild(int groupPosition, int childPosition) {
    return groups.get(groupPosition).children.get(childPosition);
  }

  @Override
  public long getChildId(int groupPosition, int childPosition) {
    return 0;
  }

  @Override
  public View getChildView(int groupPosition, final int childPosition,
      boolean isLastChild, View convertView, ViewGroup parent) {
        final String children = (String) getChild(groupPosition, childPosition);
        convertView = inflater.inflate(R.layout.listrow_details2, null);
        text = (TextView) convertView.findViewById(R.id.expandable_list_child_view2);

        // Complicated code where I create a bitmap programmatically and set
        // it as drawable on the TextView along with the appropriate text.

    return convertView;
  }

  @Override
  public int getChildrenCount(int groupPosition) {
    return groups.get(groupPosition).children.size();
  }

  @Override
  public Object getGroup(int groupPosition) {
    return groups.get(groupPosition);
  }

  @Override
  public int getGroupCount() {
    return groups.size();
  }

  @Override
  public void onGroupCollapsed(int groupPosition) {
    super.onGroupCollapsed(groupPosition);
  }

  @Override
  public void onGroupExpanded(int groupPosition) {
    super.onGroupExpanded(groupPosition);
  }

  @Override
  public long getGroupId(int groupPosition) {
    return 0;
  }

  @Override
  public View getGroupView(int groupPosition, boolean isExpanded,
      View convertView, ViewGroup parent) {
    if (convertView == null) {
      convertView = inflater.inflate(R.layout.listrow_group2, null);
    }
    Group group = (Group) getGroup(groupPosition);
    ((TextView) convertView).setText(group.string);
    ((TextView)  convertView).setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_launcher, 0, 0, 0);



    //((TextView) convertView).setChecked(isExpanded);

    return convertView;
  }

  @Override
  public boolean hasStableIds() {
    return false;
  }

  @Override
  public boolean isChildSelectable(int groupPosition, int childPosition) {
    return true;
  }

} 
Run Code Online (Sandbox Code Playgroud)

子布局:listrow_details2.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:paddingLeft="40dp" >

    <TextView
        android:id="@+id/expandable_list_child_view2"
        android:clickable="true"
        android:background="@layout/transparent_text_selector"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:drawablePadding="5dp"
        android:gravity="top|left"
        android:text="@string/hello_world"
        android:textSize="14sp" >
    </TextView>

   <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#d3d3d3" />

</LinearLayout> 
Run Code Online (Sandbox Code Playgroud)

Jus*_*ing 9

您将要使用2个不同的视图持有者.首先,让我们定义一个ViewHolder类.

public class ViewHolder
{
    private HashMap<Integer, View> storedViews = new HashMap<Integer, View>();

    public ViewHolder()
    {
    }

    /**
     * 
     * @param view
     *            The view to add; to reference this view later, simply refer to its id.
     * @return This instance to allow for chaining.
     */
    public ViewHolder addView(View view)
    {
        int id = view.getId();
        storedViews.put(id, view);
        return this;
    }

    public View getView(int id)
    {
        return storedViews.get(id);
    }
}
Run Code Online (Sandbox Code Playgroud)

我们想在getGroupView方法和getChildView方法中使用ViewHolder .

    @Override
    public View getChildView(int groupPosition, final int position,
           boolean isLastChild, View convertView, ViewGroup parent)
    {
        View row = convertView;
        if (row == null)
        {
            row = inflater.inflate(R.layout.my_layout_for_row, parent, false);
            View myView = row.findViewById(R.id.myView);
            ViewHolder holder = new ViewHolder();
            holder.addView(myView);
            row.setTag(holder);
        }

        // Get the stored ViewHolder that also contains our views
        ViewHolder holder = (ViewHolder) row.getTag();
        View myView = holder.getView(R.id.myView);
        return row;
    }
Run Code Online (Sandbox Code Playgroud)

我们对groupView方法做同样的事情.

@Override
    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent)
    {
        View v = convertView;
        if (v == null)
        {
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = inflater.inflate(R.layout.my_layout, parent, false);
            ViewHolder holder = new ViewHolder();
            holder.addView(v.findViewById(R.id.myView));
            v.setTag(holder);
        }

        ViewHolder holder = (ViewHolder) v.getTag();
        // Do whatever you need to with the group view
        return v;
    }
Run Code Online (Sandbox Code Playgroud)

编辑:也许有必要对ViewHolder的实际工作方式进行一些解释.

其中的代码if(row == null)仅用于首次初始化视图.每当新行想知道要使用什么布局时,此视图就会在convertView字段中传递.我们在此视图上设置了ViewHolder,这样我们就不必每次都调用findViewById或者扩展布局,这两者都是相对昂贵的操作.因此,当转换视图不为null时,它不会进入if语句,我们所关心的只是为ViewHolder中包含的视图设置自定义值.