0

i have a GridView with an custom BaseAdapter. In each cell i(or user) can choose(trough a button) between 3 layouts(small, medium, large) to inflate. If i choose small, every cell gets the layout small:

public View getView(final int position, View convertView, ViewGroup parent) {
    // TODO Auto-generated method stub
    if(convertView == null) {
        View temporaryView = myInflater.inflate(R.layout.activity_dialog_box, (ViewGroup) myDialogBox.getWindow().getDecorView().findViewById(android.R.id.content));
        Button scaleButton = (Button) temporaryView.findViewById(R.id.dialog_button_scale);
        switch (scaleButton.getText().toString()) {
        case "small":
            Log.e("small","true");
            convertView = myInflater.inflate(R.layout.customadapter_view_layout_small, parent, false);
            myImg = (ImageView) convertView.findViewById(R.id.imageview_layout_normal_portrait_sizesmall);
            myLabelTextView = (TextView) convertView.findViewById(R.id.textview_label_layout_normal_portrait_sizesmall);
            myABCTextView = (TextView) convertView.findViewById(R.id.textview_abc_layout_normal_portrait_sizesmall);
            break;

        case "medium":
            Log.e("medium","true");
            convertView = myInflater.inflate(R.layout.customadapter_view_layout_medium, parent, false);
            myImg = (ImageView) convertView.findViewById(R.id.imageview_layout_normal_portrait_sizemedium);
            myLabelTextView = (TextView) convertView.findViewById(R.id.textview_label_layout_normal_portrait_sizemedium);
            myABCTextView = (TextView) convertView.findViewById(R.id.textview_abc_layout_normal_portrait_sizemedium);
            break;

        case "large":
            Log.e("large","true");
            convertView = myInflater.inflate(R.layout.customadapter_view_layout_large, parent, false);
            myImg = (ImageView) convertView.findViewById(R.id.imageview_layout_normal_portrait_sizelarge);
            myLabelTextView = (TextView) convertView.findViewById(R.id.textview_label_layout_normal_portrait_sizelarge);
            myABCTextView = (TextView) convertView.findViewById(R.id.textview_abc_layout_normal_portrait_sizelarge);
            break;

        default:
            break;
        }

        convertView.setTag(new Holder(myImg, myLabelTextView, myABCTextView));

At Startup, for every Cell which fits on the Screen, convertView is null. So the Switch case and the inflating of the layout and the initialization of the ImagView and the two TextViews happens quite often. For this case let's say user selected small:

switch (scaleButton.getText().toString()) {
        case "small":
            Log.e("small","true");
            convertView = myInflater.inflate(R.layout.customadapter_view_layout_small, parent, false);
            myImg = (ImageView) convertView.findViewById(R.id.imageview_layout_normal_portrait_sizesmall);
            myLabelTextView = (TextView) convertView.findViewById(R.id.textview_label_layout_normal_portrait_sizesmall);
            myABCTextView = (TextView) convertView.findViewById(R.id.textview_abc_layout_normal_portrait_sizesmall);
            break;

(Bad for Performance). So i thought, why don't set the rootView for the specific layout-size in a seperate thread:

private View inflateLayout() {
    View myTestView = null;
    switch (scaleButtonText) {
    case "small":
        myTestView = myInflater.inflate(R.layout.customadapter_view_layout_small, (ViewGroup) gv, false);
        break;

    case "medium":
        myTestView = myInflater.inflate(R.layout.customadapter_view_layout_medium, (ViewGroup) gv, false);
        break;

    case "large":
        myTestView = myInflater.inflate(R.layout.customadapter_view_layout_large, (ViewGroup) gv, false);
        break;

    default:
        break;
    }

    return myTestView;
}

Where gv is my GridView. And give it to the adapter:

myCustomAdapter = new NewCustomAdapter(myActivityContext, myTestView);

And later, simply set convertView to myTestView in the getView method:

case "small":
            Log.e("small","true");
            convertView = myTestView;
            myImg = (ImageView) convertView.findViewById(R.id.imageview_layout_normal_portrait_sizesmall);
            myLabelTextView = (TextView) convertView.findViewById(R.id.textview_label_layout_normal_portrait_sizesmall);
            myABCTextView = (TextView) convertView.findViewById(R.id.textview_abc_layout_normal_portrait_sizesmall);
            break;

The Advantage would be that i don't have to inflate the layout again and again and again at starting the app.

The Problem: I miss something. Because the layout isn't really inflated, the GridView doesn't really exist or just in a messy condition. Can somebody explain me why it can't work like this or what i'm missing. Any help is appreciated.

MMike
  • 598
  • 3
  • 23
  • 1
    Try to use getViewTypeCount() and getItemViewType(int position) : http://stackoverflow.com/questions/4777272/android-listview-with-different-layout-for-each-row – Haresh Chhelana Nov 26 '14 at 13:08
  • @HareshChhelana thank you for your repsone. can you provide an example regarding to my code while i study the link you posted. Would be a nice Support. – MMike Nov 26 '14 at 14:17
  • @HareshChhelana i think this is not what i want or Need, i don't want to add two seperate layouts in my gridview i only want to add one of three(small,medium,large) at runtime... i think there is nothing different to my Switch case...my question was why can't i set the rootView from my layout ONE TIME and reuse it again and again instead of inflating layout for every visible cell again and again.. – MMike Nov 26 '14 at 14:27

1 Answers1

0

It seems you have a misunderstanding on how adapters work. The getView() is called quite often. There's no guarantee on what order nor how often it'll be fired. For instance, you could see it invoked 3-4 times per position. This is all normal. While there are things you can do to mitigate the performance hit, you must be careful in what you try to optimize. Adapters are already highly tuned by Android to perform as fast as possible. Trying to be smarter then the adapter by trying to inflate the view's in a separate thread. Not a good idea.

From the adapter's perspective, you do not own the Views. It does and it does a ton of things behind the scenes with those Views...to include performance optimizations. The adapter will automatically recycle views for you in order to reduce how many times you need to inflate. When convertView != null, you have a recycled view. When convertView == null, you have to inflate a new view. There's no getting around that. Sometimes the adapter is just creating throw away views with the getView for the sole purpose of measuring how large the ListView needs to be.

One way to improve the performance is to utilize the ViewHolder paradigm, which I see you are already doing.

If you dynamically change the small, medium, large layout during runtime, then another tip is to use getViewTypeCount() and getItemViewType(). Internally Android keeps a cache of views for each type. So for your case, it'll keep three pools of caches for each of your 3 switch cases...instead of one pool for all of them.

I will say that these lines:

   View temporaryView = myInflater.inflate(R.layout.activity_dialog_box, (ViewGroup) myDialogBox.getWindow().getDecorView().findViewById(android.R.id.content));
    Button scaleButton = (Button) temporaryView.findViewById(R.id.dialog_button_scale);

are confounding. To inflate then search for a view solely to know what view to inflate IS a place where you can optimize. You should determine this information outside of the getView method and pass into the adapter a value which it can use to determine what switch case to follow.

I'm not sure what else is going on with your getView but from what you posted, you shouldn't see any performance hit that will affect user experience. If you have the time, I highly recommend watching the Google IO talk "The World of ListView". Its a great video that goes in depth about how the ListView and adapters work, what you should and shouldn't do, and common pitfalls people have.

Ifrit
  • 6,791
  • 8
  • 50
  • 79