1

When I create a class extends BaseAdapter, I get a warning message

Unconditional layout inflation from view adapter: Should use View Holder pattern (use recycled view passed into this method as the second parameter) for smoother scrolling

Do I need to change my code like this suggestion? All my code is running smoothly, it's just whether it is necessary to change the code to do updata code with the latest styles? Or just need to add @SuppressLint({ "ViewHolder", "InflateParams" }) ?

My adapter

public View getView(int position, View convertView, ViewGroup parent) {
    View v = inflater.inflate(R.layout.list_item, null);

    TextView merchant_type = (TextView) v.findViewById(R.id.merchant_type);
    TextView merchant_name = (TextView) v.findViewById(R.id.merchant_name);
    TextView merchant_location = (TextView) v.findViewById(R.id.merchant_location);

    VoucherBean obj = (VoucherBean) getItem(position);

    merchant_type.setText(obj.getMerchantType());
    merchant_name.setText(obj.getMerchantName());
    merchant_location.setText(obj.getMerchantLocation());

    return v;
}

If you want to change my code as recommended above warning, like what my code later? Sorry if my question is too basic for a beginner

Bertho Joris
  • 1,483
  • 5
  • 27
  • 60

2 Answers2

5

if you have more data in your list view then you should use recycling, because it improves scrolling and performance also. here is code look like if you use view holder in your adapter.

your ViewHolder looks like

public  class ViewHolder {

        public TextView merchant_type;
        public TextView merchant_name;
        public TextView merchant_location;

    }

and your getView method

    View vi = convertView;
        ViewHolder holder;

        if (convertView == null) {

            vi = inflater.inflate(R.layout.list_item, null);

            holder = new ViewHolder();
            holder.merchant_type  = (TextView) vi.findViewById(R.id.merchant_type);
            holder.merchant_name  = (TextView) vi.findViewById(R.id.merchant_name);
            holder.merchant_location  = (TextView) vi.findViewById(R.id.merchant_location);

            vi.setTag(holder);

        } else
            holder = (ViewHolder) vi.getTag();

        // now set your text view here like 

          holder.merchant_name.setText("Bla Bla Bla");


        // return your view
        return vi;
Vishal Makasana
  • 960
  • 2
  • 7
  • 15
  • like most people here you mislead and mix up view recycling and view holder pattern, they are two different things – pskink Mar 24 '15 at 11:05
  • @pskink I know the differences of View Recycling and View Holder Pattern . But can you tell me what is the purpose of only using View Holder style ? I think it does not impact on performance. – Vishal Makasana Mar 24 '15 at 11:19
  • @DroidDev view holder in most cases is useless, i never use it. Btw none of android's adapters use view holder pattern as well – pskink Mar 24 '15 at 11:22
  • @pskink sorry but i really not completely agree with you. view Holder improves performance by reducing call -->findviewbyid if you notice that. then I think it is not completely useless ?? – Vishal Makasana Mar 24 '15 at 11:29
  • @DroidDev read this http://daniel-codes.blogspot.com/2013/11/is-findviewbyid-slow.html?m=1 – pskink Mar 24 '15 at 11:32
  • @pskink I read it. but you also read reply from "Mayank Jain" to that blog. there is a difference betweeen 400ms and 120ms, well this not big but difference is difference. – Vishal Makasana Mar 24 '15 at 11:42
  • @DroidDev i dont trust him: he measures findViewById with currentTimeMillis which is useless as each call for findViewById is < 1ms, try to measure it by yourself with System.nanoTime() or SystemClock.elapsedRealtimeNanos() and you will see.. – pskink Mar 24 '15 at 11:51
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/73659/discussion-between-droiddev-and-pskink). – Vishal Makasana Mar 24 '15 at 11:52
2

The View Holder pattern is meant to make your code easier to read and to maintain. If you look at the standard ViewHolder you'll see that its a class that basically does what you do in your getView:

private static class ExampleViewHolder{

    TextView merchant_type;
    TextView merchant_name; 
    TextView merchant_location; 

    public ExampleViewHolder(View view){
       merchant_type = (TextView) v.findViewById(R.id.merchant_type);
       merchant_name = (TextView) v.findViewById(R.id.merchant_name);
       merchant_location = (TextView) v.findViewById(R.id.merchant_location);
    } 
}

Then in your getView method you'd get your view like this:

ExampleViewHolder holder = new ExampleViewHolder(view);
view.setTag(holder);

It's good to have them and the newer apis kind of force the use of this pattern, however as you can see by the code it doesn't change much besides readability and ease of maintenance.

However! There is an important part of the getView method that you are missing, and is most likely the reason for the warning.

The listview recycles the views, and gives them back to the adapter so that the same view doesnt have to be inflated everytime. Saves resources and a lot of memory, and you're not making use of this very important aspect of the listView.

You see, the way it recycles views is passing the old view, that you inflated before, back to the adapter through the convertView, so if the convertView is not null you can be sure its the inflated layout that you are using. So use that instead of inflating a new one:

View view = convertView;
ExampleViewHolder holder;
if(view == null){//means convertView is also null
  view = inflater.inflate(yourlayout, parent, false);
  holder = new ExampleViewHolder(view);
view.setTag(holder);
}else{
  holder = (ExampleViewHolder) view.getTag();
}