0

I see a lot of SO posts about the usefulness of using convertView in Adapters, like this one, this one or this one (and many others...)

I have an ArrayAdapter, but I create the view from scratch, with a simple horizontal LinearLayout in which I add some textviews. The number of textviews and their weight depend on the position in the list. There could be 3 TV in the first row, 7 in the second and 25 in the third, with each one having a different weight, depending on database.

In this case, since I cannot inflate anything, whats does convertView contains ?

Should I use it ? If yes, how could I ?

EDIT : here is my code :

@Override
public View getView(final int position, View convertView, ViewGroup parent){
    LinearLayout layout = new LinearLayout(context);
    for (int i = 0; i < totalTVNumber; i++) {
        LifeEvent event = getEventFromDB(cost, position);
        if (event != null) {
            TextView eventTV = event.getTextView(getContext());
            eventTV.setLayoutParams(new LinearLayout.LayoutParams(0, 100, weight));//0 en width sinon weight n'est pas pris en compte !!
            layout.addView(eventTV);
        }
    }
}
Community
  • 1
  • 1
Dan Chaltiel
  • 7,811
  • 5
  • 47
  • 92

2 Answers2

2

whats does convertView contains ?

It contains a past View that you created from scratch, that has scrolled off the screen and is eligible for recycling.

Should I use it ?

Yes, please.

If yes, how could I ?

The same way that everybody else does. The fact that you are creating your views directly rather than via inflation does not matter.

So, you can do something like this:

class YourAdapter extends ArrayAdapter<Whatever> {
    @Override
    public View getView(int position, View convertView,
                          ViewGroup parent) {
      if (convertView==null) {
        convertView=newView(parent);
      }

      bindView(position, convertView);

      return(convertView);
    }

    private View newView(ViewGroup parent) {
      // create and return your new View
    }

    private void bindView(int position, View row) {
      // populate the widgets of your new or recycled view
    }
  }
CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • OK, so the convertview contains a linearlayout with textviews. Using convertView is like getting the layout, remove the textviews and adding others, how is that worth it ? (or maybe I didn't get something :s) – Dan Chaltiel Jun 19 '16 at 20:00
  • @DanChaltiel: "Using convertView is like getting the layout, remove the textviews and adding others" -- no. You retrieve the `TextViews` and call `setText()` on them, to replace their existing text with whatever you want the new text to be. In my code skeleton in the answer, you would do that work in `bindView()`, whether `row` came from inflation, recycling, or is something brand new. Feel free to use [the view-holder pattern](https://developer.android.com/training/improving-layouts/smooth-scrolling.html#ViewHolder) if you wish to simplify access to the `TextView` widgets. – CommonsWare Jun 19 '16 at 20:05
  • My bad, I didn't add enough details, but as I said @Farbod, the number and the weight of my textviews depend on the position in the list. If it was like what I understand of your post, it would be better to inflate from XML, no ? I added some code if you wanna check – Dan Chaltiel Jun 19 '16 at 20:08
  • @DanChaltiel: "the number and the weight of my textviews depend on the position in the list" -- it needs to depend on the view type returned by your `ListAdapter` via `getItemViewType()`. Otherwise, recycling will not work. And, if you are not going to recycle rows, it is unclear whether using `ListView` is the appropriate solution. – CommonsWare Jun 19 '16 at 20:10
  • I'm used to ListViews, and `getView()` is handy for thinking views, but you are right somehow, I could use a vertical ScrollView with nested layouts... Still, for a final answer, I cannot use convertView in my situation, right ? – Dan Chaltiel Jun 19 '16 at 20:14
0

ArrayAdapter automatically does the recycling of the views for you. Hence you don't need to handle yourself in case of Array Adapter. Please refer the below code I pulled from ArrayAdapter.java. You might get clarity from this.

public View getView(int position, View convertView, ViewGroup parent) {
        return createViewFromResource(mInflater, position, convertView, parent, mResource);
    }

    private View createViewFromResource(LayoutInflater inflater, int position, View convertView,
            ViewGroup parent, int resource) {
        View view;
        TextView text;

        if (convertView == null) {
            view = inflater.inflate(resource, parent, false);
        } else {
            view = convertView;
        }

        try {
            if (mFieldId == 0) {
                //  If no custom field is assigned, assume the whole resource is a TextView
                text = (TextView) view;
            } else {
                //  Otherwise, find the TextView field within the layout
                text = (TextView) view.findViewById(mFieldId);
            }
        } catch (ClassCastException e) {
            Log.e("ArrayAdapter", "You must supply a resource ID for a TextView");
            throw new IllegalStateException(
                    "ArrayAdapter requires the resource ID to be a TextView", e);
        }

        T item = getItem(position);
        if (item instanceof CharSequence) {
            text.setText((CharSequence)item);
        } else {
            text.setText(item.toString());
        }

        return view;
    }
Arpit Ratan
  • 2,976
  • 1
  • 12
  • 20