如何实现一个视图持有者(View Holder)?

11

我正在使用一个viewholder来展示一个动态的arrayadapter。虽然它起作用,但是当我滚动列表时,显示的数据会不规则地变化。我希望我的List View只被填充一次,而不是每次我滚动列表时都被填充。请问有什么建议吗?

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

   // A ViewHolder keeps references to children views to avoid unneccessary calls            
   // to findViewById() on each row.            
   ViewHolder holder;            
   // When convertView is not null, we can reuse it directly, there is no need            
   // to reinflate it. We only inflate a new View when the convertView supplied            
   // by ListView is null.            

   if (convertView == null) {                

    convertView = mInflater.inflate(R.layout.sample, null);   
    // Creates a ViewHolder and store references to the two children views                
    // we want to bind data to.               
    holder = new ViewHolder();                
    holder.name = (TextView) convertView.findViewById(R.id.text);               
    holder.icon = (ImageView) convertView.findViewById(R.id.icon);                
    convertView.setTag(holder);            
   } else {                
    // Get the ViewHolder back to get fast access to the TextView                
    // and the ImageView.


    holder = (ViewHolder) convertView.getTag();

   }            


   // Bind the data efficiently with the holder. 
   if(_first==true)
   {
   if(id<myElements.size())
   {
      holder.name.setText(myElements.get(id)); 
   holder.icon.setImageBitmap( mIcon1 );
   id++;
   }
   else
   {
    _first=false;
   }
   }
    //holder.icon.setImageBitmap(mIcon2);
   /*try{
    if(id<myElements.size())
     id++;
     else
     {
      id--;
     } 
   }
   catch(Exception e)
   {
    android.util.Log.i("callRestService",e.getMessage());
   }*/



   return convertView;

  }        
static class ViewHolder {            
 TextView name;            
 ImageView icon;        
}  
当列表加载时,它看起来像这样:http://i.stack.imgur.com/NrGhR.pngalt text。当滚动一些数据后,它看起来像这样:http://i.stack.imgur.com/sMbAD.pngalt text。如果我滚动到开头,它看起来像这样:http://i.stack.imgur.com/0KjMa.pngalt text。我的列表必须按字母顺序排列。

你能发布一下你的输出屏幕截图吗? - Sankar Ganesh PMP
@Tilsan The Fighter:已经发布了快照。 - Ads
2个回答

27

你试过这个吗?

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

   // A ViewHolder keeps references to children views to avoid unneccessary calls            
   // to findViewById() on each row.            
   ViewHolder holder;            
   // When convertView is not null, we can reuse it directly, there is no need            
   // to reinflate it. We only inflate a new View when the convertView supplied            
   // by ListView is null.            

   if (convertView == null) {                

    convertView = mInflater.inflate(R.layout.sample, null);   
    // Creates a ViewHolder and store references to the two children views                
    // we want to bind data to.               
    holder = new ViewHolder();                
    holder.name = (TextView) convertView.findViewById(R.id.text);               
    holder.icon = (ImageView) convertView.findViewById(R.id.icon);                
    convertView.setTag(holder);            
   } else {                
    // Get the ViewHolder back to get fast access to the TextView                
    // and the ImageView.


    holder = (ViewHolder) convertView.getTag();

   }            


   // Bind the data efficiently with the holder. 
   holder.name.setText(myElements.get(id)); 
   holder.icon.setImageBitmap( mIcon1 );

   return convertView;
  }  

static class ViewHolder {            
    TextView name;            
    ImageView icon;        
} 

如果是这样,有什么问题吗?

我不认为一次性加载所有行是一个好主意。 这会导致内存中有大量无用的视图,这些视图什么也做不了却会拖慢应用程序的速度。 视图和对视图的操作(如膨胀,findViewById,getChild..)是昂贵的,您应该尽可能重复使用它们。 这就是为什么我们使用ViewHolders的原因。


是的!我尝试过了。当我滚动到最后一个元素(>92)时,它无法加载列表视图中的元素!myElement是一个arrayList,通过id帮助我获取每个元素以在文本视图中显示。是的,看起来我一次性加载了所有数据,但我不知道如何重复使用它,你能帮忙吗? - Ads

5
您需要自己编写ListView的版本来完成这个操作(这很糟糕)。如果ListView无法正常工作,那么很可能是您做错了什么。 id元素从哪里来?您可以在getView()方法中获取位置,因此不必担心超出列表边界。位置与列表中的元素位置相关联,因此您可以按如下方式获取正确的元素:
myElements.get(position);

当您的列表中的数据发生更改时,您可以调用此函数:
yourAdapter.notifyDataSetChanged()

那会使用新数据重建你的列表(同时保持你的滚动和其他设置)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接