Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement a view holder?

i am using a viewholder to display from a dynamic arrayadapter.it works but the data displayed changes irregularly when i scroll the List.i want my List View to be populated only once ,Not all the time when i scroll my list. Any suggestion? Here is my Code

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

when the list is loaded it looks like this : http://i.stack.imgur.com/NrGhR.png alt text after scrolling some data http://i.stack.imgur.com/sMbAD.png alt text it looks like this, and again if i scroll to the beginning it looks http://i.stack.imgur.com/0KjMa.pngalt text

P.S : my list have to be in alphabetic order

like image 797
Ads Avatar asked Nov 10 '10 14:11

Ads


People also ask

What is a view holder?

A ViewHolder describes an item view and metadata about its place within the RecyclerView. Adapter implementations should subclass ViewHolder and add fields for caching potentially expensive findViewById results. While LayoutParams belong to the LayoutManager , ViewHolders belong to the adapter.

When on Create view holder is called?

onCreateViewHolder is called when you need a new View. by Pavlos-Petros Tournaris | Medium. This is not the way a recycling works.

Which method must be overridden to implement a RecyclerView adapter?

Override onBindViewHolder instead if Adapter can handle efficient partial bind. The ViewHolder which should be updated to represent the contents of the item at the given position in the data set. The position of the item within the adapter's data set.


2 Answers

Have you tried this?

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

If yes, what's wrong with it?

I don't think loading all the rows at once is a good idea. You will end up having plenty of useless Views in memory that are going to slow the application down for nothing. Views and operations on views (like inflate, findViewById, getChild..) are expensive, you should try to reuse them as much as possible. That's why we use ViewHolders.

like image 60
nbarraille Avatar answered Sep 28 '22 04:09

nbarraille


You would need to write you own version of ListView to do that (which is bad). If the ListView doesn't work properly, it probably means that you are doing something wrong.

Where does the id element come from? You are getting the position in your getView() method, so you don't need to worry about exceeding list bounds. The position is linked to the element position in your list, so you can get the correct element like this:

myElements.get(position);

When the data in your list changes, you can call this:

yourAdapter.notifyDataSetChanged()

That will rebuild your list with new data (while keeping your scrolling and stuff).

like image 30
Alex Orlov Avatar answered Sep 28 '22 04:09

Alex Orlov