Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Optimizing UI Performance in Android Apps

Optimizing UI Performance in Android Apps

Sriram Ramani

November 29, 2013
Tweet

More Decks by Sriram Ramani

Other Decks in Programming

Transcript

  1. “a lot snappier now” Firefox for Android “starts up quicker”

    “best overall browser experience” “tablet version was "Buttery" Smooth!”
  2. Number of times a pixel on the screen is touched

    1x Blue 2x Green 3x Red 4+ Deep Red Show GPU Overdraw
  3. Time taken to draw each frame Green line is 16ms

    mark Blue update lists Red process lists Yellow swap buffers Profile GPU Rendering
  4. Time taken to draw each frame Green line is 16ms

    mark Blue update lists Red process lists Yellow swap buffers Profile GPU Rendering
  5. import com.sriramramani.droid.inspector.server.ViewServer; ! public class MyActivity extends Activity { !

    @Override public void onCreate(Bundle ofJoy) { super.onCreate(ofJoy); ViewServer.get(this).addWindow(this); } ! @Override public void onDestroy() { super.onDestroy(); ViewServer.get(this).removeWindow(this); } ! @Override public void onResume() { super.onResume(); ViewServer.get(this).setFocusedWindow(this); } }
  6. <!—— Problem ——> <style name="Theme.Holo.Light" parent=“Theme.Light”> <item name=“windowBackground"> @android:drawable/screen_background_selector_light </item>

    </style> ! ! ! ! ! ! // Solution @Override public void onWindowFocusChanged(boolean hasFocus) { ! super.onWindowFocusChanged(hasFocus); ! // Reset the background getWindow().setBackgroundDrawable(null); }
  7. Compound Drawables Merging an ImageView (icon) with the TextView (label)

    And the drawables support states! Accompanying Label
  8. Compound Drawables Merging an ImageView (icon) with the TextView (label)

    And the drawables support states! Accompanying Label
  9. <LinearLayout android:layout_width=“match_parent” android:layout_height=“match_parent”> ! <ImageView android:layout_width=“24dp” android:layout_height=“24dp” android:src=“@drawable/icon”/> ! <TextView

    android:layout_width=“0dip” android:layout_height=“match_parent” android:paddingLeft=“10dp” android:text=“Label”/> ! </LinearLayout>
  10. <TextView android:layout_width=“match_parent” android:layout_height=“match_parent” android:drawableLeft=“@drawable/icon” android:drawablePadding=“10dp” android:text=“Label”/> ! ! ! !

    textView.setCompoundDrawables(left, top, right, bottom); ! textView.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom); ! textView.setCompoundDrawablesRelative(start, top, end, bottom);
  11. SpannableStringBuilder builder = new SpannableStringBuilder(_text_); ! ForegroundColorSpan foreground = new

    ForegroundColorSpan(0xFFFF0000); ! builder.setSpan(foreground, startIndex, endIndex, Spanned.SPAN_INCLUSIVE_INCLUSIVE); ! mTextView.setText(builder, BufferType.SPANNABLE);
  12. @Override public void draw(Canvas canvas) { canvas.save(); ! // Ask

    parent to draw. This is the DST. super.draw(canvas); ! // Create an off-screen bitmap. Bitmap mask = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); // Draw the path on the bitmap. This is the SRC. (new Canvas(mask)).drawPath(mPath, mPaint); // Draw the bitmap containing the path, over the actual canvas. mPaint.setXfermode(new PorterDuffXfermode(Mode.DST_IN)); canvas.drawBitmap(mask, 0, 0, mPaint); // Reset paint, as it will be used again to draw a path on a bitmap. mPaint.setXfermode(null); ! canvas.restore(); }
  13. Shaders Horizontal spans of colors during drawing Added to the

    Paint of the Canvas Analogous to a paint brush in Photoshop Paint with a color is the simplest shader
  14. public void setImage(Bitmap bitmap) { BitmapShader bitmapShader = new BitmapShader(mBitmap,

    Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); mPaint.setShader(bitmapShader); } ! ! ! ! ! @Override public void draw(Canvas canvas) { // Draw the bitmap. canvas.drawPath(mPath, mPaint); }
  15. public void setImage(Bitmap bitmap) { BitmapShader bitmapShader = new BitmapShader(mBitmap,

    Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); ! LinearGradient gradient = new LinearGradient(0, 0, 0, bitmap.getHeight(), 0xFF000000, 0x0, Shader.TileMode.CLAMP); // bitmap is the DST. gradient is the SRC. mPaint.setShader(new ComposeShader(bitmapShader, gradient, PorterDuff.Mode.DST_IN)); } ! ! @Override public void draw(Canvas canvas) { // Draw the bitmap. canvas.drawPaint(mPaint); }
  16. @Override protected void onMeasure(Canvas canvas) { // Ask the parent

    to set the padding. super.onMeasure(widthMeasureSpec, heightMeasureSpec); ! int children = (mContacts == null) ? 0 : mContacts.length; ! int eachChildWidth = mChildSize + (2 * mChildMargin); ! int width = getPaddingLeft() + getPaddingRight() + (children * eachChildWidth); ! setMeasuredDimension(width, getMeasuredHeight()); }
  17. @Override protected void onDraw(Canvas canvas) { canvas.save(); ! // Translate

    the canvas. canvas.translate(getPaddingLeft(), ((getHeight() - mChildSize)/2)); ! final int length = mShaders.length; ! for (int i = 0; i < length; i++) { canvas.translate(mChildMargin, 0); ! // Set the child shader. mPaint.setShader(mShaders[i]); ! canvas.drawRoundRect(mChildBounds, mChildCorner, mChildCorner, mPaint); ! canvas.translate(mChildSize + mChildMargin, 0); } ! canvas.restore(); }