BaseAdapter.getView() for ListActivty using ViewHolder - Android

10,695

Here when you have inflated view at that time you should use layout

so change from this

 convertView = mInflater.inflate(R.id.gridviewViewOutfits, null);

to

  convertView = mInflater.inflate(R.layout.gridviewViewOutfits, null);
Share:
10,695
user3164083
Author by

user3164083

Updated on June 04, 2022

Comments

  • user3164083
    user3164083 almost 2 years

    This was my original getView method for the ListView BaseAdapter:

        // create a new ImageView for each item referenced by the Adapter
            public View getView(int position, View convertView, ViewGroup parent) {
                ImageView imageView;
                if (convertView == null) {  // if it's not recycled, initialize some attributes
                    imageView = new ImageView(mContext);
                    imageView.setLayoutParams(new GridView.LayoutParams(150, 150));
                    imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
                    imageView.setPadding(8, 8, 8, 8);
                } else {
                    imageView = (ImageView) convertView;
                }
    
                ImageHelper ih = new ImageHelper();
    
    
    
    imageView.setImageBitmap(ih.decodeSampledBitmapFromResource(mContext.getResources(), mList.get(position), 40, 40));
    
                return imageView;
            }
    

    It did not make use of convertView and I had no mInflater. I read that this way is not good for memory usage, and I found a better way that uses a ViewHolder. I have changed this method to implement a viewHolder and use the convertView instead making an ImageView like I originally did:

    static class ViewHolder{
            TextView text;
            ImageView icon;
        }
    
        public View getView(int position, View convertView, ViewGroup parent) {
                  ViewHolder holder;
                  ImageView imageView = new ImageView(mContext);
                  ImageHelper ih = new ImageHelper();
                  if (convertView == null) {
                  convertView = mInflater.inflate(R.id.gridviewViewOutfits, null);
    
                  holder = new ViewHolder();
                  holder.icon = (ImageView) convertView;
                  holder.icon.setLayoutParams(new GridView.LayoutParams(150, 150));
                  holder.icon.setScaleType(ImageView.ScaleType.FIT_CENTER);
                  holder.icon.setPadding(8, 8, 8, 8);
    
                  convertView.setTag(holder);
                  } else {
                  holder = (ViewHolder) convertView.getTag();
                  }
    
                  holder.icon.setImageBitmap(ih.decodeSampledBitmapFromResource(mContext.getResources(), mList.get(position), 40, 40));
    
                  return convertView;
                  }
    

    This line caused a nullPointerException: convertView = mInflater.inflate(R.id.gridviewViewObjects, null);

    It's because I had not instantiated my mInflater. Then I did that like this: mInflater = (LayoutInflater)c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    Because I saw that online. Then I got this error:

    01-20 20:37:52.080: E/AndroidRuntime(22543): FATAL EXCEPTION: main
    01-20 20:37:52.080: E/AndroidRuntime(22543): android.content.res.Resources$NotFoundException: Resource ID #0x7f04002b type #0x12 is not valid
    01-20 20:37:52.080: E/AndroidRuntime(22543):    at android.content.res.Resources.loadXmlResourceParser(Resources.java:2136)
    01-20 20:37:52.080: E/AndroidRuntime(22543):    at android.content.res.Resources.getLayout(Resources.java:865)
    01-20 20:37:52.080: E/AndroidRuntime(22543):    at android.view.LayoutInflater.inflate(LayoutInflater.java:394)
    01-20 20:37:52.080: E/AndroidRuntime(22543):    at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
    01-20 20:37:52.080: E/AndroidRuntime(22543):    at com.btf271.imagehelper.ChooseStickersImageAdapter.getView(ChooseObjectsImageAdapter.java:136)
    

    What should I do to instantiate the mInflater, or am I inflating the wrong thing?

    This is my XML for the ListActivity:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context=".ViewOutfitsActivity" >
    
        <ListView
            android:id="@android:id/list"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true" >
        </ListView>
    
        <GridView
            android:id="@+id/gridviewViewObjects"
            android:layout_width="fill_parent" 
            android:layout_height="fill_parent"
            android:columnWidth="90dp"
            android:numColumns="auto_fit"
            android:verticalSpacing="10dp"
            android:horizontalSpacing="10dp"
            android:stretchMode="columnWidth"
            android:gravity="center"
        />
    
    </RelativeLayout>
    

    Thank you.

  • user3164083
    user3164083 over 10 years
    Thanks. It says "gridviewViewOutfits cannot be resolved or is not a field"
  • heri.wijoyo
    heri.wijoyo over 10 years
    then you just have to import it: import YOUR_APP_PACKAGE_NAME.R.layout.gridviewViewOutfits
  • user3164083
    user3164083 over 10 years
    Thanks. This will just display images in a gridView. Do you mean I create a whole new XML file such as the file that each Activity has created automatically? I have never done this. Would I right-click the Layout folder and click new XML file?
  • user3164083
    user3164083 over 10 years
    My gridViewViewOutfits is just a view inside my ListActivity layout. So do I right-click the layout folder and click new XML file, to create a new layout? Then inflate that? Thank you.
  • Piyush
    Piyush over 10 years
    Yes if you want to make custom list then you should use that one..And you'r going in right direction.
  • user3164083
    user3164083 over 10 years
    Thank you :) Should I give it a root element of RelativeLayout? I am creating it now and not sure what option to choose. Or should I go for ListView?
  • user3164083
    user3164083 over 10 years
    Thank you. There are a lot of root elements to choose from for my custom layout. Do I choose RelativeLayout or ListView or something else?
  • Piyush
    Piyush over 10 years
    you can use relative layout or linear layout
  • user3164083
    user3164083 over 10 years
    Thanks. It works but does not reduce the heap at all :( When I exit the listActivity I want those list bitmaps out of memory which does not appear to happen. However I will mark this as the answer.
  • Piyush
    Piyush over 10 years
    are you set background image for your layout any where which has a high resolution?
  • user3164083
    user3164083 over 10 years
    No. I have an ImageView in my main Activity which takes up the full screen. I set it to 500 X 500 px. This just has to be there though. However, the heap keeps growing when accessing the ListActivity and then does not go back down when I click the item which adds it to the main Activity. The item drawn to the main Activity is very small. It is the List that is doing it.
  • Piyush
    Piyush over 10 years
    and this is because you are fetching images from resource folder and that images may be high resolutions.
  • user3164083
    user3164083 over 10 years
    I change their resolution with inSampleSize, to 40px X 40px to draw them to the main Activity. I can confirm their resolution. The heap is growing because of the List, which is fine, but when I exit the List by clicking on an item, they should be removed from memory :(
  • Roman Black
    Roman Black over 10 years
    Yes, you should give it a root element of RelativeLayout or any other layout class
  • fweigl
    fweigl over 10 years
    Exactly, that's what you need to to. If you only want to display an Image the layout needs only to contain an ImageView. You probably want to read a tutorial like this one: vogella.com/tutorials/AndroidListView/… It's about ListViews but the adapter part is exactly the same for GridViews.
  • user3164083
    user3164083 over 10 years
    Thank you. I have finished and it works. However it was all for nothing, the heap is still just as big. I am convinced it is growing from this listView and not reducing upon exiting the ListView. Oh well, my original question has been answered well :)