Android Listview Using Viewholder

Implements ViewHolder on a ListView AndroidStudio

    public class YourAdapter extends ArrayAdapter<String> {

Context context;
int layoutResourceId;
String data[] = null;

public YourAdapter(Context context, int layoutResourceId, String[] data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
ViewHolder holder = null;

if(row == null)
{
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);

holder = new ViewHolder();
holder.txtTitle = (TextView)row.findViewById(R.id.row_textview);

row.setTag(holder);
}
else
{
holder = (ViewHolder)row.getTag();
}

String title = data[position];
holder.txtTitle.setText(title);

return row;
}

static class ViewHolder
{
TextView txtTitle;
}
}

and In your activity do this:

   YourAdapter adapter = new YourAdapter<>(this,R.layout.your_custom_layout, your_string_array);
mylist = (ListView) findViewById(R.id.listView1);
mylist.setAdapter(adapter);

ViewHolder in custom adapter of listview is not working in Android

Because you are using two different Holder Object and your another object dont not have anything
.Declare your viewHolder object out side of if statement

Like this:

@Override
public View getView(final int position,View convertView,ViewGroup parent)
{
View rowView = convertView;
ViewHolder viewHolder;
if(rowView==null)
{
LayoutInflater layoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
rowView = layoutInflater.inflate(R.layout.podcast_list_row,null);
viewHolder = new ViewHolder();

viewHolder.descriptionTextView = (TextView)rowView.findViewById(R.id.row_description);
viewHolder.titleTextView = (TextView)rowView.findViewById(R.id.row_title);
viewHolder.durationTextView = (TextView)rowView.findViewById(R.id.row_duration);
viewHolder.fileSizeTextView = (TextView)rowView.findViewById(R.id.row_file_size);
viewHolder.imageView = (ImageView)rowView.findViewById(R.id.row_image);
rowView.setTag(viewHolder);
}
else {
viewHolder = (ViewHolder) rowView.getTag();
}
viewHolder.titleTextView.setText(values.get(position).getTitle());
viewHolder.descriptionTextView.setText(values.get(position).getDescription());
viewHolder.durationTextView.setText(values.get(position).getDuration());
viewHolder.fileSizeTextView.setText(String.valueOf(values.get(position).getFileSize()));
return rowView;

}

What is the benefit of ViewHolder pattern in android?

Understand how listview recycling works

How ListView's recycling mechanism works

You cannot recycle a row that is presently in use. The above link explains how listview recycling mechanism works

So What is the benefit of using ViewHolder?

Quoting docs

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.

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

if (convertView == null) { // if convertView is null
convertView = mInflater.inflate(R.layout.mylayout,
parent, false);
holder = new ViewHolder();
// initialize views
convertView.setTag(holder); // set tag on view
} else {
holder = (ViewHolder) convertView.getTag();
// if not null get tag
// no need to initialize
}

//update views here
return convertView;
}

You missed the important part convertView.setTag(holder) and holder = (ViewHolder) ConvertView.getTag()

http://developer.android.com/training/improving-layouts/smooth-scrolling.html

How can I use Android DataBinding in a listview and still use a ViewHolder pattern?

Try this:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (inflater == null) {
inflater = ((Activity) parent.getContext()).getLayoutInflater();
}

// Perform the binding

ActivityTeamMessageListRowBinding binding = DataBindingUtil.getBinding(convertView);

if (binding == null) {
binding = DataBindingUtil.inflate(inflater, R.layout.my_activity_list_row, parent, false);
}

binding.setInfo(list.get(position));
binding.executePendingBindings();

// Return the bound view
return binding.getRoot();
}

I haven't used data binding with ListView (I'll use RecyclerView), but off the cuff, this is what I'd try. Use breakpoints or logging to confirm that, when convertView is not null, that you get binding back from getBinding() more often than not (and perhaps all the time — I'm hazy on how data binding's caching works).

Explain individual role of convertView and View Holder Pattern in ListView

  • convertView

it's a view that was previously inflated (when convertView==null) and was on the screen, but now have been scrolled out of the screen, so you can re-use it to display data from the view that will enter the screen soon.

improves performance by reducing view inflation (calls to inflater.inflate are expensive), reduces garbage collection, and reduces memory allocation.

  • view holder

keeps a direct reference to your view.

potentially improves performance because findViewById is a for-loop going around the view hierarchy that can potentially eat away quite precious time of the UI thread. This improvement might be small, but in a fast scrolling list, every nano-second counts to have a nice smoth 60fps.

ListView with Button, Using ViewHolder within OnClick

Change the code like this ,

public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder viewHolder ;
if (convertView == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
convertView = inflater.inflate(R.layout.row, null);
viewHolder = new ViewHolder();
viewHolder.text = (TextView) convertView.findViewById(R.id.playerScore);
viewHolder.button = (Button) convertView.findViewById(R.id.playerButton);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
viewHolder.button.setText(modelList.get(position).getPlayer());
}

viewHolder.button.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
//TODO UPDATE the model here
int newScore = modelList.get(position).getScore() + 1;
modelList.get(position).setScore(newScore);
viewHolder.text.setText(Integer.toString(newScore);
}
});

return convertView;
}

Using ViewHolder With ListView

Tricks:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if( convertView == null ){
convertView = LayoutInflater.from(getActivity()).inflate(R.layout.list_view_layout, null);
holder = new ViewHolder();
holder.tv=(TextView) convertView.findViewById(R.id.textView);
holder.iv=(ImageView) convertView.findViewById(R.id.imageView);
...
convertView.setTag(holder);
}else {
holder = (ViewHolder)convertView.getTag();
}

holder.tv.setText(text1[position]);
holder.iv.setImageResource(text2[position]);
...
//handle with your widgets cached in ViewHolder
return convertView;

}

And ViewHolder is here:

public class ViewHolder{
TextView tv;
ImageView iv;
}


Related Topics



Leave a reply



Submit