Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ConvertView in GetView()

I'm trying to wrap my head around getView() and I don't think there's any topic in Android that creates more confusion and questions on StackOverflow and elsewhere. Everyone wants to know why it gets called so many times or in what order or not at all, but as Romain Guy says here , " there is absolutely no guarantee on the order in which getView() will be called nor how many times."

So I have a different question: I don't understand the convertView parameter.

I have a list of 15 items, 11 of which can fit on the screen. The very first time my app starts up getView() is called 48 times.

convertView is null for position 0 on the first call, the non-null for positions 1-11, then non-null for position 0 and null for positions 1-11, then null for position 0 and non-null for positions 1-11, and finally non-null for positions 0-11.

Could someone please explain why/when convertView is null versus non-null, how/why it starts off non-null for most positions, and why the same positions seem to bounce back and forth between these two states?

References to good tutorials, written in clear English, that explain convertView in detail would also be appreciated.

PS - my tests were done on a device running Android 2.3.5, if that matters. I know Google has changed ListActivity/adapter/getView stuff several times since then.

Per request, I'm including the Adapter code (I've obscured some proprietary names). Unfortunately I can't answer any "why did you do that?" questions, since I didn't write it

protected class PLxxxAdapter extends BaseAdapter {

    public PLxxxAdapter(Context c) {
    }

    @Override
    public int getCount() {
        return listItems.size();
    }

    @Override
    public Object getItem(int position) {
        return listItems.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        boolean select;

        if (convertView == null) {              
            LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = vi.inflate(R.layout.PLxxxitem, null);
            //This is still needed even though we point to an XML description
            convertView.setLayoutParams(new ListView.LayoutParams(
                    ListView.LayoutParams.MATCH_PARENT,
                    ListView.LayoutParams.MATCH_PARENT));
            holder = new ViewHolder();

            //Get the views of the row
            holder.itemView = (TextView)convertView.findViewById(R.id.post);
            holder.cV1 = (CheckedTextView)convertView.findViewById(R.id.check1);

            //Init the 'confirm' box listener
            holder.cV1.setCompoundDrawablesWithIntrinsicBounds(0, R.layout.smallcb, 0, 0);
            holder.cV1.setOnClickListener(new ConfBoxListener());

            convertView.setTag(holder);
            holder.cV1.setTag(holder);  //These views need tags for onClick()
        }
        else {
            holder = (ViewHolder)convertView.getTag();  // convertview NOT null
        }

       try  {
          int liSize = listItems.size();
          if (position < liSize)  {
             holder.itemView.setText(listItems.get(position));
          }
       }
       catch (Exception e)  {
              Log.e ("PLxxxActivity.getView Crash", "details " + e);
       }
        holder.cV1.setChecked(confirmed.get(position));
        select = selected.get(position);

        if (select == true)   {
            convertView.setBackgroundResource(R.color.colBlue);
        }               

        else
            convertView.setBackgroundResource(R.color.colGrey);
        holder.position = position;
        if (RemoteControlActivity.confCBs == true)
            holder.cV1.setVisibility(View.VISIBLE);
        else
            holder.cV1.setVisibility(View.INVISIBLE);

        return convertView;
    }  // end getView
}  //end class PLxxxAdapter
like image 778
user316117 Avatar asked May 09 '14 18:05

user316117


People also ask

What is convertView?

convertView is the ListView Item Cache that is not visible, and hence it can be reused. It lets the ListView need not create a lot of ListItems, hence saving memeory and making the ListView more smooth.

How do I use getView?

getView. Get a View that displays the data at the specified position in the data set. You can either create a View manually or inflate it from an XML layout file. When the View is inflated, the parent View (GridView, ListView...) will apply default layout parameters unless you use LayoutInflater.

How to inflate ListView in Android?

In this case what you can do is, create a empty layout in your main activity xml. Set a ID for that. While inflating the listview, inflate it to that layout.

What is a Base Adapter in Android*?

An easy adapter to map columns from a cursor to TextViews or ImageViews defined in an XML file. Common base class of common implementation for an Adapter that can be used in both ListView (by implementing the specialized ListAdapter interface) and Spinner (by implementing the specialized SpinnerAdapter interface).


1 Answers

The first x times, where x is a number near the number of items visible on the screen, convertView is null. You need to instantiate a new View to return.

When you scroll down, an existing View is pushed upwards out of sight. Instead of destroying it, it can now be reused. You'll notice that, just before a new View is pushed in from below, your getView method is called, with a valid convertView. This is exactly that View that was pushed out of sight before (or maybe another one, there is some additional logic)!

Therefore, instead of re-instantiating your View, which is costly, you can reuse the View and adapt it to the new item it represents. You will often see something like:

View view = convertView;
if(view == null){
    view = LayoutInflater.from(getContext()).inflate(...);
}

// 'bind' view

return view;

The fact that your getView method is called 48 times on startup, might actually be an issue with your code.

like image 143
nhaarman Avatar answered Sep 27 '22 23:09

nhaarman