Mayur
Mayur

Reputation: 799

GridView is not smooth. How to optimize the grideview

I have created simple image gallery which displays images stored in res/drawable folder , but the grid view is very laggy and slow. How can I optimized the gridview further more so that the movement is smooth.

  public class ImageGalleryActivity extends Activity {
    String strCategoryName = null;
    GridView gridView;
    Utils utils;
    private int columnWidth;

    // private GridViewImageAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_image_gallery);

        Intent intent;
        intent = getIntent();
        if (intent != null) {
            strCategoryName = intent.getStringExtra("category");
        }


        gridView = (GridView) findViewById(R.id.gridView_cards);
        utils = new Utils(this);

        // Intializing Grid View
        InitilizeGridLayout();
        // gridView.setAdapter(new GridCustomAdapter(this));

        // adapter = new GridViewImageAdapter(ImageGalleryActivity.this,
        // defaultImages, columnWidth, this);

        List<Item> items = new ArrayList<Item>();
        if(strCategoryName.equals("test"))
        {
            items.add(new Item(R.drawable.i1));
            items.add(new Item(R.drawable.i2));
            items.add(new Item(R.drawable.i3));
            items.add(new Item(R.drawable.i4));
            items.add(new Item(R.drawable.i5));
            items.add(new Item(R.drawable.i6));
            items.add(new Item(R.drawable.i7));
            items.add(new Item(R.drawable.i8));
            items.add(new Item(R.drawable.i9));
            items.add(new Item(R.drawable.i10));
            items.add(new Item(R.drawable.i11));
            items.add(new Item(R.drawable.i12));
            items.add(new Item(R.drawable.i13));
            items.add(new Item(R.drawable.i14));
            items.add(new Item(R.drawable.i15));
            items.add(new Item(R.drawable.i16));
            items.add(new Item(R.drawable.i17));
            items.add(new Item(R.drawable.i18));
            items.add(new Item(R.drawable.i19));
            items.add(new Item(R.drawable.i20));
            items.add(new Item(R.drawable.i21));
            items.add(new Item(R.drawable.i22));
            items.add(new Item(R.drawable.i23));
            items.add(new Item(R.drawable.i24));
            items.add(new Item(R.drawable.i25));
        }
        else if(strCategoryName.equals("test")){
            items.add(new Item(R.drawable.i1));
            items.add(new Item(R.drawable.i2));
            items.add(new Item(R.drawable.i3));
            items.add(new Item(R.drawable.i4));
            items.add(new Item(R.drawable.i5));
            items.add(new Item(R.drawable.i6));
            items.add(new Item(R.drawable.i7));
            items.add(new Item(R.drawable.i8));
            items.add(new Item(R.drawable.i9));
            items.add(new Item(R.drawable.i10));
            items.add(new Item(R.drawable.i11));
            items.add(new Item(R.drawable.i12));
            items.add(new Item(R.drawable.i13));
            items.add(new Item(R.drawable.i14));
            items.add(new Item(R.drawable.i15));
            items.add(new Item(R.drawable.i16));
            items.add(new Item(R.drawable.i17));
            items.add(new Item(R.drawable.i18));

        }else{
            items.add(new Item(R.drawable.i1));
            items.add(new Item(R.drawable.i2));
            items.add(new Item(R.drawable.i3));
            items.add(new Item(R.drawable.i4));
            items.add(new Item(R.drawable.i5));
            items.add(new Item(R.drawable.i6));
            items.add(new Item(R.drawable.i7));
            items.add(new Item(R.drawable.i8));
            items.add(new Item(R.drawable.i9));
            items.add(new Item(R.drawable.i10));
            items.add(new Item(R.drawable.i11));
            items.add(new Item(R.drawable.i12));
            items.add(new Item(R.drawable.i13));
            items.add(new Item(R.drawable.i14));
            items.add(new Item(R.drawable.i15));
            items.add(new Item(R.drawable.i16));
            items.add(new Item(R.drawable.i17));
            items.add(new Item(R.drawable.i18));
        }



        gridView.setAdapter(new MyAdapter(this, items, columnWidth, ImageGalleryActivity.this));
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.image_gallery, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    private void InitilizeGridLayout() {

        Resources r = getResources();
        float padding = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                AppConstant.GRID_PADDING, r.getDisplayMetrics());
        columnWidth = (int) ((utils.getScreenWidth() - ((AppConstant.NUM_OF_COLUMNS + 1) * padding)) / AppConstant.NUM_OF_COLUMNS);

        gridView.setNumColumns(AppConstant.NUM_OF_COLUMNS);
        gridView.setColumnWidth(columnWidth);
        gridView.setStretchMode(GridView.NO_STRETCH);
        gridView.setPadding((int) padding, (int) padding, (int) padding,
                (int) padding);

        gridView.setHorizontalSpacing((int) padding);
        gridView.setVerticalSpacing((int) padding);
    }

}

class MyAdapter extends BaseAdapter {
    private List<Item> items;
    private Context context;
    int columnWidth;
    Activity _activity;

    public MyAdapter(Context context, List<Item> items, int columnWidth, Activity activity) {
        this.context = context;
        this.items = items;
        this.columnWidth = columnWidth;
        this._activity = activity;
    }

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

    @Override
    public Object getItem(int i) {
        return items.get(i);
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            holder = new ViewHolder();
            convertView = LayoutInflater.from(context).inflate(
                    R.layout.frame_layout_square_image_view, null, false);

            holder.picture = (ImageView) convertView.findViewById(R.id.picture);
            convertView.setTag(holder);

        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        holder.picture.setImageBitmap((decodeImage(
                items.get(position).drawableId, columnWidth)));
         holder.picture.setOnClickListener(new OnImageClickListener(items.get(position).drawableId));
        return convertView;
    }
    class OnImageClickListener implements OnClickListener {

        int _drawableId;

        // constructor
        public OnImageClickListener(int drawableId) {
            this._drawableId = drawableId;
        }

        @Override
        public void onClick(View v) {
            // on selecting grid view image
            // launch full screen activity
            Intent i = new Intent(_activity, ImageEditor.class);
            i.putExtra("drawableId", _drawableId);
            _activity.startActivity(i);
        }

    }

    class ViewHolder {

        ImageView picture;

    }

    public Bitmap decodeImage(int resourceId, int imageSize) {
        try {
            // Decode image size
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;
            BitmapFactory.decodeResource(context.getResources(), resourceId, o);
            // The new size we want to scale to
            final int REQUIRED_SIZE = imageSize; // you are free to modify size
                                                    // as your requirement

            // Find the correct scale value. It should be the power of 2.
            int scale = 1;
            while (o.outWidth / scale / 2 >= REQUIRED_SIZE
                    && o.outHeight / scale / 2 >= REQUIRED_SIZE)
                scale *= 2;

            // Decode with inSampleSize
            BitmapFactory.Options o2 = new BitmapFactory.Options();
            o2.inSampleSize = scale;
            return BitmapFactory.decodeResource(context.getResources(),
                    resourceId, o2);
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return null;

    }

}

class Item {

    final int drawableId;

    Item(int drawableId) {
        this.drawableId = drawableId;
    }

}

Upvotes: 0

Views: 580

Answers (3)

AmaJayJB
AmaJayJB

Reputation: 1453

I was having the same problem as you with a very unsmooth scrolling experience. I agree with Mate Krizanac - basically what you want to do is do any image loading on a thread that isn't the main UI thread. So you could use Picasso or ImageLoader class, or alternatively use a AsyncTask to load the image into your ViewHolder. Another way to optimize would be to scale the images down a bit. There is plenty of code online that can help you with that. Hope this helps. Let me know if you need actual code to explain.

Upvotes: 0

synapticvoid
synapticvoid

Reputation: 34

First I think that this line:

holder.picture.setOnClickListener(new OnImageClickListener(items.get(position).drawableId));

is quite heavy, you allocate an anonymous class at each getView call. If you really want to be sure you can track your memory allocation (http://developer.android.com/tools/debugging/ddms.html#alloc).

What you could easily do is a listener member that you allocate only once :

private OnClickListener myImageClickListener = new OnImageClickListener();

And then in your getView you just

holder.picture.setOnClickListener(myImageClickListener);

To have a more "generic" listener you could (in your getView):

holder.picture = (ImageView) convertView.findViewById(R.id.picture);
holder.picture.setTag(items.get(position).drawableId);

And then:

@Override
    public void onClick(View v) {
        int drawableId = Integer.valueOf(v.getTag());
}

That might already ease the pain :)

Upvotes: 0

M.Khouli
M.Khouli

Reputation: 4122

Try gridView.setSmoothScrollbarEnabled(true); it will use a more refined calculation method based on the pixels height of the items visible on screen. http://developer.android.com/reference/android/widget/GridView.html Hope this may help.

Upvotes: 2

Related Questions