I have a class that extends from ImageView (well actually are three classes that extends one from the other, but that's not relevant) to perform some custom drawing around the drawable drawn by the ImageView. Now, my code is fine (or at least I think is fine, after having profiled it it takes just a bunch of ms to run) but when setting the image (image loaded as a Bitmap) everything hangs for about 500 ms, not a lot but enough to be noticeable.
Sadly this class has to be used inside a GridView (or ListView) and everything is fine until, after the images have been load (through Picasso, so obviously my problem is not the loading of the image on the main thread), the images are set in the imageviews. Now, since each ImageView takes some hundreds ms to display the image it makes the GridView lag while scrolling if images are being set.
Now as you can see from the image below (results of method profiling provided by DDMS) what takes so much time is the method GLES20Canvas.nDrawDisplayList
Note: The images are down scaled to a size a little lower respect the ImageView, so this solution has already been tried.
Now to the question: How can I display in an efficient and fast manner this Bitmap?
Thank you all in advance!
EDIT: Time for some code, as asked by JakeWharton
@Override
public boolean onPreDraw() {
if (mNeedRedraw)
updateAttrs();
return true;
}
@Override
protected void onDraw(Canvas canvas) {
canvas.save();
if (mClippingPath != null) {
canvas.clipPath(mClippingPath);
}
super.onDraw(canvas);
canvas.restore();
if (mBorderPath != null && mBorderPaint != null) {
canvas.drawPath(mBorderPath, mBorderPaint);
}
}
Now the other three subclass have a really similar code, obviously the mNeedRedraw
flag is set only when really needed since it recalculate all the things needed for a correct drawing (but always reusing objects, no object allocation is done in the updateAttrs()
method.
Just for completeness sake:
The draw of the first subclass:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mBackgroundPaint != null && mBackgroundPath != null) {
canvas.drawPath(mBackgroundPath, mBackgroundPaint);
canvas.drawTextOnPath(mText, mBackgroundPath, mHorizontalOffset, mMidTextHeight, mTextPaint);
if (mIcon != null && mIconTransformationMatrix != null) {
canvas.drawBitmap(mIcon, mIconTransformationMatrix, mTextPaint);
}
}
}
@Override
public boolean onPreDraw() {
boolean result = super.onPreDraw();
if (mFooNeedRedraw)
updateAttrs();
return result;
}
The draw of the second subclass:
@Override
public boolean onPreDraw() {
boolean result = super.onPreDraw();
if (mBarNeedRedraw)
updateAttrs();
return result;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mArc != null && !isInEditMode()) {
canvas.drawPath(mArc, mArcPaint);
}
}
And finally the code of the last subclass:
@Override
public boolean onPreDraw() {
boolean result = super.onPreDraw();
if (mBazNeedRedraw || mTrackNeedRedraw)
updateAttrs();
return result;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(mTrackVisible)
canvas.drawBitmap(mThumbTrackIcon, mThumbIconTransformationMatrix, mThumbPaint);
}
This is all. Now, the updateAttrs()
is a private method, there are no relations between them in the subclasses, I have checked how many times it is called, and for my test seems to be called only two times at the first creation / activity recreation.
Any Idea?