Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Layout Traversals (GDG Devfest 2014)
Search
Lucas Rocha
November 15, 2014
Technology
550
9
Share
Layout Traversals (GDG Devfest 2014)
Presented at GDG Devfest London 2014
Lucas Rocha
November 15, 2014
More Decks by Lucas Rocha
See All by Lucas Rocha
Layout Traversals (Droidcon Turin 2015)
lucasr
16
630
Design-Engineering Workflow
lucasr
2
440
Custom Layouts
lucasr
34
2k
Introducing Smoothie
lucasr
7
520
Bringing Firefox to Android
lucasr
6
610
A Million Times Pattrn
lucasr
6
440
Mozilla & Mobile
lucasr
2
210
The State of Firefox Mobile
lucasr
1
2.2k
Other Decks in Technology
See All in Technology
AWS DevOps Agentはチームメイトになれるのか?/ Can AWS DevOps Agent become a teammate
kinunori
6
740
Digitization部 紹介資料
sansan33
PRO
1
7.3k
プラットフォームエンジニアリングの実践 - AWS コンテナサービスで構築する社内プラットフォーム / AWS Containers Platform Meetup #1
literalice
1
170
M5Stack CoreS3とZephyr(RTOS)で Edge AIっぽいことしてみた
iotengineer22
0
220
社内エンジニア勉強会の醍醐味と苦しみ/tamadev
nishiuma
0
210
Introduction to Sansan for Engineers / エンジニア向け会社紹介
sansan33
PRO
6
74k
自立を加速させる神器 - EMOasis #11
stanby_inc
0
140
マルチエージェント × ハーネスエンジニアリング × GitLab Duo Agent Platformで実現する「AIエージェントに仕事をさせる時代へ。」 / 20260421 GitLab Duo Agent Platform
n11sh1
0
160
みんなで作るAWS Tips 100連発 (FinOps編)
schwrzktz
1
300
弁護士ドットコム株式会社 エンジニア職向け 会社紹介資料
bengo4com
1
150
AI時代のガードレールとしてのAPIガバナンス
nagix
0
280
生成AIが変える SaaS の競争原理と弁護士ドットコムのプロダクト戦略
bengo4com
0
760
Featured
See All Featured
Balancing Empowerment & Direction
lara
6
1.1k
KATA
mclloyd
PRO
35
15k
Navigating Weather and Climate Data
rabernat
0
170
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
1
5.6k
Java REST API Framework Comparison - PWX 2021
mraible
34
9.3k
Being A Developer After 40
akosma
91
590k
Game over? The fight for quality and originality in the time of robots
wayneb77
1
160
Kristin Tynski - Automating Marketing Tasks With AI
techseoconnect
PRO
0
230
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.4k
How to optimise 3,500 product descriptions for ecommerce in one day using ChatGPT
katarinadahlin
PRO
1
3.5k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
2.8k
Making Projects Easy
brettharned
120
6.6k
Transcript
LAYOUT TRAVERSALS Devfest London, 2014
LUCAS ROCHA +LucasRocha | @lucasratmundo
None
BE DELIBERATE Less handwaviness in your UI code
UI TOOLKITS Layout + Rendering + Input Events
TICK TOCK VSYNC sets the pace.
CHOREOGRAPHER f1 f2 f3 f4 f5 . . . .
. . VSYNC (60fps) Resize view Redraw view Input Events
CHOREOGRAPHER 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.java
ViewRootImpl Connects WindowManager with the View framework
ViewRootImpl *
FRAMEWORK Measure + Layout + Draw
TRAVERSAL * performTraversals() f2 performTraversals()
MEASURE * measure(int, int) f2 M M M M M
M → onMeasure(int, int) measureHierarchy(...)
LAYOUT * f2 M L M L M L M
L M L M L layout(int, int, int, int) → onLayout(boolean, int, int, int, int) performLayout()
DRAW * f2 M L D M L D M
L D M L D M L D M L D draw(Canvas) → onDraw(Canvas) performDraw()
CHANGES Resize, redraw & animate.
* requestLayout() f1 f2 f3 f4 f5 . . .
. . .
requestLayout() public void requestLayout() { ... if (mParent != null
&& !mParent.isLayoutRequested()) { mParent.requestLayout(); } ... } void scheduleTraversals() { ... mTraversalBarrier = mHandler.getLooper().postSyncBarrier(); mChoreographer.postCallback( Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null); ... } View.java ViewRootImpl.java
* Invalidate(...) f1 f2 f3 f4 f5 . . .
. . .
invalidate(...) public void invalidateInternal(...) { ... mPrivateFlags |= PFLAG_DIRTY; ...
if (mParent != null && mAttachInfo != null && l < r && t < b) { final Rect damage = mAttachInfo.mTmpInvalRect; damage.set(l, t, r, b); mParent.invalidateChild(this, damage); } ... } View.java
* postOnAnimation() f1 f2 f3 f4 f5 . . .
. . . ValueAnimator ...
postOnAnimation() public void postOnAnimation(Runnable action) { ... attachInfo.mViewRootImpl.mChoreographer.postCallback( Choreographer.CALLBACK_ANIMATION, action,
null); ... } void doFrame(long frameTimeNanos, int frame) { ... doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos); doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos); doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos); ... } View.java Choreographer.java
LAZY MEASURE Multi-MeasureSpec cache, invalidated in requestLayout()
LAZY MEASURE 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; } ... } View.java
LAZY MEASURE 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; } ... } View.java
BASIC TIPS 1. No layout requests during layout 2. No
layout requests during animations 3. Invalidate regions when possible
PERFORMANCE 1. Simplify your view hierarchy 2. Avoid multi-pass measurement
GO CUSTOM Simplify view hierarchy, performance, missing features. http://lucasr.org/?p=3920
TREE OBSERVER Use OnPreDrawListener!
TRANSITIONS http://lucasr.org/?p=3902
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. } }
PROBE IT! Intercept view methods. Dissect layout traversals. https://github.com/lucasr/probe
OVERRIDE VIEW METHODS public class DrawGreen extends Interceptor { private
final Paint mPaint; public DrawGreen() { mPaint = new Paint(); mPaint.setColor(Color.GREEN); } @Override public void onDraw(View view, Canvas canvas) { canvas.drawPaint(mPaint); } }
DEPLOY public final class MainActivity extends Activity { @Override protected
void onCreate(Bundle savedInstanceState) { Probe.deploy(this, new DrawGreen(), new Filter.ViewId(R.id.view2)); super.onCreate(savedInstanceState); setContentView(R.id.main_activity); } }
WRAP VIEW METHODS public class LogRequestLayout extends Interceptor { @Override
public void requestLayout(View view) { super.requestLayout(view); Log.d(LOGTAG, “requestLayout() on ” + view); } }
QUESTIONS? +LucasRocha | @lucasratmundo