optymalizacja hierarchii widoków na platformie android

44
Optymalizacja hierarchii widoków na platformie Android Michał Włodarczyk, Mobilization 2015, Łódź

Upload: open-rnd

Post on 12-Jan-2017

538 views

Category:

Mobile


1 download

TRANSCRIPT

Page 1: Optymalizacja hierarchii widoków na platformie Android

Optymalizacja hierarchii widoków na

platformie Android

Michał Włodarczyk, Mobilization 2015, Łódź

Page 2: Optymalizacja hierarchii widoków na platformie Android

Jak tworzyć wydajne aplikacje?

Page 3: Optymalizacja hierarchii widoków na platformie Android

“Layout Traversals on Android”

Lucas RochaFacebook Inc.

DroidCon 2015, Berlin

Page 4: Optymalizacja hierarchii widoków na platformie Android

Pozycjonowanie

Rysowanie

Interakcje ze zdarzeniami

Czym jest UI dla programisty?

Page 5: Optymalizacja hierarchii widoków na platformie Android

Początki Android’a były trudne ...

Page 6: Optymalizacja hierarchii widoków na platformie Android

Przed Jelly Bean

ViewRoot.java

public final class ViewRoot extends Handler ... {

...

public void scheduleTraversals() { if (!mTraversalScheduled) { mTraversalScheduled = true; sendEmptyMessage(DO_TRAVERSAL);

} } ... public void handleMessage(Message msg) {

... case DO_TRAVERSAL: performTraversals(); ...

} }

Page 7: Optymalizacja hierarchii widoków na platformie Android

Odświeżanie ekranu w przewidywalnych odstępach czasu

Page 8: Optymalizacja hierarchii widoków na platformie Android

Od Jelly Bean - Choreographer

... f1 f2 f3 f4 f5 ...

Resize view

Redrawview

InputEvents

Page 9: Optymalizacja hierarchii widoków na platformie Android

Choreographer.java

public void onVsync(long timestampNanos, int builtInDisplayId, int frame) { ... scheduleVsync(); ...

}

...

void doFrame(long frameTimeNanos, int frame) { ... if (!mFrameScheduled) {

return; } ... doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos); ...

}

Choreographer

Page 10: Optymalizacja hierarchii widoków na platformie Android

ViewRootlmpl

Łączy zarządcę okien z hierarchią widoków

Page 11: Optymalizacja hierarchii widoków na platformie Android

SurfaceFlinger

ViewRootImpl

Hierarchia widoków

Page 12: Optymalizacja hierarchii widoków na platformie Android

Metody związane z widokami

Measure + Layout + Draw

Page 13: Optymalizacja hierarchii widoków na platformie Android

measureHierarchy(...)

measure(int, int) → onMeasure(int, int)

M M M

M M

M

*

Measure

Page 14: Optymalizacja hierarchii widoków na platformie Android

Lazy Measure

Multi-MeasureSpec cache

Page 15: Optymalizacja hierarchii widoków na platformie Android

View.java

public final void measure(int widthMeasureSpec, int heightMeasureSpec) {

... int cacheIndex = mMeasureCache.indexOfKey(key); if (cacheIndex < 0 || sIgnoreMeasureCache) {

onMeasure(widthMeasureSpec, heightMeasureSpec); mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;

} else { long value = mMeasureCache.valueAt(cacheIndex); setMeasuredDimensionRaw((int) (value >> 32), (int) value); mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;

} ...

}

Lazy Measure

Page 16: Optymalizacja hierarchii widoków na platformie Android

View.java

public void layout(int l, int t, int r, int b) { if ((flags & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0 ) {

onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec); mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;

} ...

}

Lazy Measure

Page 17: Optymalizacja hierarchii widoków na platformie Android

RelativeLayout

LinearLayout Button

LinearLayout TextView

RelativeLayout RelativeLayout

TextView TextViewTextView TextView TextView TextView

requestLayout()

Multi-MeasureSpace cache

Page 18: Optymalizacja hierarchii widoków na platformie Android

18 19

6.5 ms 0.7 ms

72 14

SDK

czas mierzenia

ilość wywołań

Multi-MeasureSpace cache

Page 19: Optymalizacja hierarchii widoków na platformie Android

layout(int, int, int, int) → onLayout(boolean, int, int, int, int)

M L M L M L

M L M L

M L

*

Layout

performLayout()

Page 20: Optymalizacja hierarchii widoków na platformie Android

performDraw()

draw(Canvas) → onDraw(Canvas)M L D

*

M L D M L DM L D

M L D M L DDraw

Page 21: Optymalizacja hierarchii widoków na platformie Android

View.java

private DisplayList getDisplayList(...) { ... final HardwareCanvas canvas = displayList.start(width, height); ... draw(canvas); ... displayList.end(); ...

}

Display List

Page 22: Optymalizacja hierarchii widoków na platformie Android

Kiedy wykonywany jest layout(), to na pewno zrobiony jest measure()

Kiedy wykonywany jest draw(), to na pewno zrobiony jest layout()

Pamiętaj!

Page 23: Optymalizacja hierarchii widoków na platformie Android

1. Wywołanie getMeasured*() poza onLayout()

2. Alokacja:● onLayout(): Akceptowalna● onMeasure(): Unikać● onDraw(): Nigdy

Unikaj!

Page 24: Optymalizacja hierarchii widoków na platformie Android

Zmiany rozmiaru elementów, odświeżenie stanu, animacje

Page 25: Optymalizacja hierarchii widoków na platformie Android

... f1 f2 f3 f4 f5 ...

Metoda requestLayout()

*

requestLayout()

Page 26: Optymalizacja hierarchii widoków na platformie Android

View.java

public void requestLayout() { ... if (mParent != null && !mParent.isLayoutRequested()) { mParent.requestLayout(); } ...

}

ViewRootImpl.java

void scheduleTraversals() { ... mChoreographer.postCallback( Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null); ...

}

Metoda requestLayout()

Page 27: Optymalizacja hierarchii widoków na platformie Android

Metoda invalidate()

... f1 f2 f3 f4 f5 ...

*

invalidate(...)

Page 28: Optymalizacja hierarchii widoków na platformie Android

Metoda invalidate()

View.java

public void invalidateInternal(...) { ... mPrivateFlags |= PFLAG_INVALIDATED; ... if (mParent != null && mAttachInfo != null && l < r && t < b) {

final Rect damage = mAttachInfo.mTmpInvalRect; damage.set(l, t, r, b); mParent.invalidateChild(this, damage);

} ...

}

boolean draw(...) { ... mRecreateDisplayList = (

mPrivateFlags & PFLAG_INVALIDATED) == PFLAG_INVALIDATED; ...

}

Page 29: Optymalizacja hierarchii widoków na platformie Android

Metoda postOnAnimation()

...... f1 f2 f3 f4 f5 ...

*postOnAmination()valueAnimator...

Page 30: Optymalizacja hierarchii widoków na platformie Android

Metoda postOnAnimation()

View.java

public void postOnAnimation(Runnable action) { ... attachInfo.mViewRootImpl.mChoreographer.postCallback(

Choreographer.CALLBACK_ANIMATION, action, null);...

}

Choreographer.java

void doFrame(long frameTimeNanos, int frame) { ... doCallbacks(Choreographer.CALLBACK_INPUT,frameTimeNanos); doCallbacks(Choreographer.CALLBACK_ANIMATION,frameTimeNanos); doCallbacks(Choreographer.CALLBACK_TRAVERSAL,frameTimeNanos); ...

}

Page 31: Optymalizacja hierarchii widoków na platformie Android

Używajmy OnPreDrawListener!

Tree Observer

Page 32: Optymalizacja hierarchii widoków na platformie Android

OnPreDrawListener

// 1. Save layout state and wait for next frame.

getViewTreeObserver().addOnPreDrawListener(new OnPreDrawListener() {@Override public boolean onPreDraw() {

getViewTreeObserver().removeOnPreDrawListener(this);

// 2. Restore original layout state. // 3. Trigger animators towards new layout state.

} }

Page 33: Optymalizacja hierarchii widoków na platformie Android

Nie wywołuj layout() podczas layout

Nie wywołuj layout() podczas animacji

Wywołuj invalidate() tylko na tych elementach, które chcesz przerysować

Pamiętaj!

Page 34: Optymalizacja hierarchii widoków na platformie Android

1. Prosta hierarchia widoków2. Multi pass layout - unikajmy

Wydajność

Page 35: Optymalizacja hierarchii widoków na platformie Android

Własne widoki

Page 36: Optymalizacja hierarchii widoków na platformie Android

1. Composite Views2. Custom Composite Views3. Flat Custom Views

Własne widoki

Page 37: Optymalizacja hierarchii widoków na platformie Android

Przydatne narzędzia

Page 38: Optymalizacja hierarchii widoków na platformie Android

Hierarchy Viewer

źródło: http://cfile10.uf.tistory.com/image/110412354E5A61652D1F2C

Page 39: Optymalizacja hierarchii widoków na platformie Android

Stereovision Image Calculator

Page 40: Optymalizacja hierarchii widoków na platformie Android

Stereovision Image Calculator

Page 41: Optymalizacja hierarchii widoków na platformie Android

1. Menu zmienione z RelativeLayout na FrameLayout

2. Uproszczenie hierarchii widoków3. Wykres jako Custom Flat View4. Kolejkowanie odświeżania

Stereovision Image Calculator Optymalizacja

Page 42: Optymalizacja hierarchii widoków na platformie Android

Nexus 7

Nexus 7 po optymalizacja

Samsung Tab 2

Samsung tab 2 po optymalizacja

Stereovision Image CalculatorWyniki optymalizacji

299.03

50.54

478.42

65.92

Czas renderowania [ms]

Page 43: Optymalizacja hierarchii widoków na platformie Android

Po co tworzyć wydajne aplikacje?

Page 44: Optymalizacja hierarchii widoków na platformie Android

[email protected]

QUESTIONS ? THOUGHTS ? COMMENTS ?

Feel free to contact us!

WWW.OPEN-RND.PL

Thank you

Michał WłodarczykSENIOR SOFTWARE DEVELOPER of Open-RnD

[email protected]