Android UI Development: Tips, Tricks, and Techniques
Romain Guy Chet Haase Android UI Toolkit Team Google
rrific Tips, e T y ll Tota
Android UI Development: Tricks, and Techniques
Romain Guy Chet Haase Android UI Toolkit Team Google
Trash Talk
Trash Talk
or
Garbage Zero
Avoid creating garbage, when necessary and possible
Statics as Temporaries
Instead of a temporary object:
public boolean pointInArea(int x, int y, Area area) { Point testPoint = new Point(x, y); return area.intersect(testPoint); }
Consider a static instead:
static final Point tmpPoint = new Point(); public boolean pointInArea(int x, int y, Area area) { tmpPoint.x = x; tmpPoint.y = y; return area.intersect(tmpPoint.yPoint); }
5
AutoBoxing
Autoboxing creates Objects
float x = 5; Float y = x; doSomething(x); void doSomething(Float z) {}
is equivalent to
float x = 5; Float y = new Float(x); doSomething(new Float(x)); void doSomething(Float z) {}
6
De-Autoboxing
Use primitive types whenever possible
Avoids Object creation
Use types you need for the situation
Avoids autoboxing back and forth
Obliterator
The enhanced for() loop is great ... but creates garbage
for (Node node : nodeList) {}
is equivalent to
Iterator iter = nodeList.iterator(); while (iter.hasNext()) {}
Consider a size check first:
if (nodeList.size() > 0) { for (Node node : nodeList) {} }
Image is Everything
Recycle those Bitmaps
Device resources are limited
Finalizers will clear them ... eventually You might think this would help
// done using this one, clear reference myBitmap = null;
But you really want to do this
// done using this one, recycle it myBitmap.recycle();
Dont wait for the finalizer to do the work if you need that memory now
9
Varargh
Parameters to varargs method packaged into a temporary array
void someMethod(float... args) {} someMethod(5f);
is equivalent to
someMethod(new float[]{5});
10
Gener-ick
T doesnt stand for primitive Type
public class MyClass<T> { T myVar; MyClass<T>(T arg) { myVar = arg; } }
Generics only deal with Objects; primitive types get autoboxed
float f; MyClass<Float> myObject = new MyClass<Float>(f);
which is equivalent to
MyClass<Float> myObject = new MyClass<Float>(new Float(f));
11
Tools: Allocation Tracking
Limit allocations to find problems
int prevLimt = -1; try { prevLimit = Debug.setAllocationLimit(0); // Do stuff } finally { Debug.setAllocationLimit(-1); }
Count the allocations being made
Debug.startAllocationCounting(); // do stuff int allocCount = Debug.getThreadAllocCount(); Debug.stopAllocationCounting);
12
Tools: DDMS
Visual tool helps track allocations down to the object/file/line number (demo)
13
Watch the Garbage... But Dont Be Silly
As Michael Abrash might have said:
Premature optimization is the Root of all evil
ViewRoot
Minor garbage is irrelevant in most cases But if you have GCs at critical points in your application, consider Garbage Zero
Example: animations
14
Tools: hat
DDMS Heap Analysis Tool is used to track down memory leaks adb shell dumpsys meminfo <process>
15
Memory leaks
Be careful with Context Be careful with static fields Avoid non-static inner classes Use weak references
16
YOU and I
Responsiveness
Single-threaded UI Dont block the UI thread
Also called main thread
AsyncTask
Worker thread and UI thread messaging
Handler
Messaging
18
Overinvalidating
Only redraw what you must (demo)
19
Fewer is better
Many views
Slower layout Slower drawing Slower startup time
Deep hierarchies
Memory Slow... StackOverflowException
20
HiearchyViewer
Layout optimizations
Custom views Custom layouts <merge /> ViewStub Compound drawables layoutopt
22
ViewStub
23
ViewStub
24
ViewStub
<ViewStub android:id="@+id/stub_import" android:inflatedId="@+id/panel_import" android:layout="@layout/progress_overlay" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" />
25
ViewStub
findViewById(R.id.stub_import).setVisibility(View.VISIBLE); // or View importPanel = ((ViewStub) findViewById(R.id.stub_import)).inflate();
26
<merge/>
27
<merge/>
<!-- The merge tag must be the root tag --> <merge xmlns:android="http://schemas.android.com/apk/res/android"> <!-- Content --> </merge>
28
Compound drawables
<LinearLayout android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/icon" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello" /> </LinearLayout>
29
Compound drawables
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello" android:drawableLeft="@drawable/icon" />
30
layoutopt
ListView
1 public View getView(int position, View convertView, ViewGroup parent) { 2 View item = mInflater.inflate(R.layout.list_item_icon_text, null); 3 4 5 6 7 } ((TextView) item.findViewById(R.id.text)).setText(DATA[position]); ((ImageView) item.findViewById(R.id.icon)).setImageBitmap( (position & 1) == 1 ? mIcon1 : mIcon2); return item;
32
ListView
1 public View getView(int position, View convertView, ViewGroup parent) { 2 if (convertView == null) { 3 convertView = mInflater.inflate(R.layout.item, parent, false); 4 } 5 6 7 8 9 } ((TextView) convertView.findViewById(R.id.text)).setText(DATA[position]); ((ImageView) convertView.findViewById(R.id.icon)).setImageBitmap( (position & 1) == 1 ? mIcon1 : mIcon2); return convertView;
33
ListView
static class ViewHolder { TextView text; ImageView icon; }
34
ListView
1 public View getView(int position, View convertView, ViewGroup parent) { 2 ViewHolder holder; 3 4 if (convertView == null) { 5 convertView = mInflater.inflate(R.layout.list_item_icon_text, 6 parent, false); 7 holder = new ViewHolder(); 8 holder.text = (TextView) convertView.findViewById(R.id.text); 9 holder.icon = (ImageView) convertView.findViewById(R.id.icon); 10 11 convertView.setTag(holder); 12 } else { 13 holder = (ViewHolder) convertView.getTag(); 14 } 15 16 holder.text.setText(DATA[position]); 17 holder.icon.setImageBitmap((position & 1) ==? mIcon1 : mIcon2); 18 19 return convertView; 20 }
35
ListView
60.0 50.0 40.0 30.0 20.0 10.0 0
Dumb Correct Fast List of 10,000 items on NexusOne, Android 2.2
36
Graphics optimizations
Pre-scale bitmaps Use compatible bitmaps
ARGB_8888 to draw on 32 bits window
Avoid blending Use View drawing caches
View.setDrawingCacheEnabled(true)
View.isOpaque()
37
For More Information
Android developer site
developer.android.com
Romain
@romainguy curious-creature.org
Chet
@chethaase graphics-geek.blogspot.com
38