Android的 - 可扩展的ListView - 使用ViewHolder优化 [英] Android - Expandable ListView - using ViewHolder for optimization

查看:160
本文介绍了Android的 - 可扩展的ListView - 使用ViewHolder优化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个ListView,其中每一行是一个图像+文字。我已经使用ViewHolder优化的滚动实施这个列表作为一个单独的列表。
现在我试图使用相同的视觉效果,但这次作为一个可扩展的ListView的一部分。我这样做,虽然视觉上看起来一样,自然滚动发粘...所以现在的问题是:

我如何使用ViewHolder技术在可扩展的ListView?

我想象的东西必须在完成日getChildView()方法,但我没有足够的经验与这一技术由我自己想出的细节。这里是适配器和子布局。任何帮助将大大AP preciated !!

 公共类MyExpandableListAdapter2扩展BaseExpandableListAdapter {  私人最终SparseArray<组>组;
  公共LayoutInflater吹气;
  公共活动活动;  公共MyExpandableListAdapter2(活动行为,SparseArray<组>组){
    活性=行为;
    this.groups =组;
    充气= act.getLayoutInflater();
  }  @覆盖
  公共对象getChild(INT groupPosition,诠释childPosition){
    返回groups.get(groupPosition).children.get(childPosition);
  }  @覆盖
  众长getChildId(INT groupPosition,诠释childPosition){
    返回0;
  }  @覆盖
  公共查看getChildView(INT groupPosition,最终诠释childPosition,
      布尔isLastChild,查看convertView,父母的ViewGroup){
        最后弦乐的孩子=(字符串)getChild(groupPosition,childPosition);
        convertView = inflater.inflate(R.layout.listrow_details2,NULL);
        文字=(TextView的)convertView.findViewById(R.id.expandable_list_child_view2);        //复杂code其中我创建位图编程和设置
        //它作为TextView的绘制与相应的文本一起。    返回convertView;
  }  @覆盖
  公众诠释getChildrenCount(INT groupPosition){
    返回groups.get(groupPosition).children.size();
  }  @覆盖
  公共对象getGroup(INT groupPosition){
    返回groups.get(groupPosition);
  }  @覆盖
  公众诠释getGroupCount(){
    返回groups.size();
  }  @覆盖
  公共无效onGroupCollapsed(INT groupPosition){
    super.onGroupCollapsed(groupPosition);
  }  @覆盖
  公共无效onGroupExpanded(INT groupPosition){
    super.onGroupExpanded(groupPosition);
  }  @覆盖
  众长getGroupId(INT groupPosition){
    返回0;
  }  @覆盖
  公共查看getGroupView(INT groupPosition,布尔isExpanded,
      查看convertView,父母的ViewGroup){
    如果(convertView == NULL){
      convertView = inflater.inflate(R.layout.listrow_group2,NULL);
    }
    群组=(集团)getGroup(groupPosition);
    ((的TextView)convertView).setText(group.string);
    ((的TextView)convertView).setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_launcher,0,0,0);    //((的TextView)convertView).setChecked(isExpanded);    返回convertView;
  }  @覆盖
  公共布尔hasStableIds(){
    返回false;
  }  @覆盖
  公共布尔isChildSelectable(INT groupPosition,诠释childPosition){
    返回true;
  }}

子布局:listrow_details2.xml

 < LinearLayout中的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
    的xmlns:工具=htt​​p://schemas.android.com/tool​​s
    机器人:layout_width =match_parent
    机器人:layout_height =WRAP_CONTENT
    机器人:方向=垂直
    机器人:paddingLeft =40dp>    <的TextView
        机器人:ID =@ + ID / expandable_list_child_view2
        机器人:可点击=真
        机器人:背景=@布局/ transparent_text_selector
        机器人:layout_width =match_parent
        机器人:layout_height =WRAP_CONTENT
        机器人:drawablePadding =5DP
        机器人:重力=顶|左
        机器人:文字=@字符串/参考hello world
        机器人:TEXTSIZE =14sp>
    < / TextView的>   <查看
        机器人:layout_width =match_parent
        机器人:layout_height =1DP
        机器人:背景=#d3d3d3/>< / LinearLayout中>


解决方案

您会想使用2个不同的观点的持有者。首先,让我们定义一个类ViewHolder

 公共类ViewHolder
{
    私人的HashMap<整数,视图> storedViews =新的HashMap<整数,视图>();    公共ViewHolder()
    {
    }    / **
     *
     * @参数视图
     *视图增加;后来引用这一观点,只是指其ID。
     返回:此实例允许链接。
     * /
    公共ViewHolder addView(查看视图)
    {
        INT ID = view.getId();
        storedViews.put(ID,视图);
        返回此;
    }    公共查看getView(INT ID)
    {
        返回storedViews.get(ID);
    }
}

我们要使用的ViewHolder在 getGroupView 方法,并在 getChildView 方法。

  @覆盖
    公共查看getChildView(INT groupPosition,最终诠释的位置,
           布尔isLastChild,查看convertView,父母的ViewGroup)
    {
        查看排= convertView;
        如果(行== NULL)
        {
            行= inflater.inflate(R.layout.my_layout_for_row,父母,假);
            查看MyView的= row.findViewById(R.id.myView);
            ViewHolder持有人=新ViewHolder();
            holder.addView(MyView的);
            row.setTag(保持器);
        }        //获取存储ViewHolder也包含了我们的意见
        ViewHolder支架=(ViewHolder)row.getTag();
        查看MyView的= holder.getView(R.id.myView);
        返回行;
    }

我们做同样的事情为groupView方法。

  @覆盖
    公共查看getGroupView(INT groupPosition,布尔isExpanded,查看convertView,父母的ViewGroup)
    {
        视图V = convertView;
        如果(V == NULL)
        {
            LayoutInflater吹气=(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            V = inflater.inflate(R.layout.my_layout,父母,假);
            ViewHolder持有人=新ViewHolder();
            holder.addView(v.findViewById(R.id.myView));
            v.setTag(保持器);
        }        ViewHolder支架=(ViewHolder)v.getTag();
        //做任何你需要与组视图
        返回伏;
    }

编辑:也许解释一点点的质保期为ViewHolder如何工作

的code。如果(行== NULL)仅用于初始化的第一次的意见。这一观点得到了convertView领域每一个新行想知道用什么什么布局阵子过去了。我们设置ViewHolder这一观点,所以我们不必调用findViewById每次充气或布局,这两者都是相对昂贵的操作做到这一点被传来传去。所以,当转换的观点是不为空,它不进去,如果语句和我们关心为包含在里面ViewHolder的意见是设置自定义值。

I have a ListView where every row is an image+text. I have implemented this list as a seperate list using a ViewHolder to optimize scrolling. Now I'm trying to use the same visual effect but this time as part of an Expandable ListView. I did that and while visually it looks the same, naturally the scrolling is sticky...So the question is:

How can I use the ViewHolder technique in an Expandable ListView?

I imagine that something must be done within th getChildView() method but I'm not experienced enough with this technique to figure out the details by my self. Here is the Adapter and the child layout. Any help will be greatly appreciated !!

 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;
  }

} 

child layout: 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> 

解决方案

You're going to want to use 2 different view holders. First, let's define a ViewHolder class.

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);
    }
}

We want to use the ViewHolder in the getGroupView method and in the getChildView method.

    @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;
    }

We do the same thing for the groupView method.

@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;
    }

EDIT: Perhaps a little bit of explanation is warranted for how ViewHolder actually works.

The code inside the if(row == null) is only for initializing the views for the first time. This view gets passed around in the convertView field every time a new row wants to know what to what layout to use. We set the ViewHolder on this view that gets passed around so we don't have to call findViewById every time or inflate the layout, both of which are relatively expensive operations. So, when the convert view isn't null, it doesn't go in that if-statement and all we care about is setting custom values for the views contained inside the ViewHolder.

这篇关于Android的 - 可扩展的ListView - 使用ViewHolder优化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆