Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Deflating the LayoutInflater
Search
Saket Narayan
August 28, 2016
Programming
1.6k
5
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Deflating the LayoutInflater
https://droidconin.talkfunnel.com/2016/86-deflating-the-layoutinflater
Saket Narayan
August 28, 2016
Transcript
89 slides
Deflating the LayoutInflater Saket • Uncommon
Parts 1. What and how 2. Applications
Part 1, What is LayoutInflater
Converts View hierarchies written in XML into Java objects XML
<TextView android:layout_width="wrap_content" android:layout_height=“wrap_content" /> Java public class TextView extends View { ... }
Common Usages
Fragments @Override public View onCreateView(LayoutInflater, ViewGroup, Bundle) { return inflater.inflate(
R.layout.fragment_layout, container, false ); }
ViewHolders @Override public ViewHolder onCreateViewHolder(ViewGroup, int) { return new ViewHolder(inflater.inflate(
R.layout.fragment_layout, container, false )); }
Activities @Override protected void onCreate(Bundle savedState) { super.onCreate(savedState); setContentView(R.layout.activity_main); }
PhoneWindow.java (or AppCompatDelegateImplV7.java) @Override public void setContentView(int layoutRes) { mLayoutInflater.inflate(layoutRes,
mParent); }
How it works
LayoutInflater#inflate() A. XmlPullParser B. AttributeSet C. Creating View objects
LayoutInflater#inflate() A. XmlPullParser GSON, Moshi for JSON is the same
as XmlPullParser for XML
LayoutInflater#inflate() B. AttributeSet <ImageView android:layout_width="100dp" android:layout_height="100dp" android:src="@drawable/ic_done" android:contentDescription="Save" />
LayoutInflater#inflate() B. AttributeSet <ImageView android:layout_width="100dp" android:layout_height="100dp" android:src="@drawable/ic_done" android:contentDescription="Save" />
LayoutInflater#inflate() B. AttributeSet <ImageView android:layout_width="100dp" android:layout_height="100dp" android:src="@drawable/ic_done" android:contentDescription="Save" />
LayoutInflater#inflate() B. AttributeSet <ImageView android:layout_width="100dp" android:layout_height="100dp" android:src="@drawable/ic_done" android:contentDescription="Save" />
LayoutInflater#inflate() B. AttributeSet <ImageView android:layout_width="100dp" android:layout_height="100dp" android:src="@drawable/ic_done" android:contentDescription="Save" />
LayoutInflater#inflate() B. AttributeSet <ImageView android:layout_width="100dp" android:layout_height="100dp" android:src="@drawable/ic_done" android:contentDescription="Save" />
LayoutInflater#inflate() B. AttributeSet <ImageView android:layout_width="@dimen/list_icon" android:layout_height="@dimen/list_icon" android:src="@drawable/ic_done" android:contentDescription="Save" /> res/values/dimens.xml
LayoutInflater#inflate() B. AttributeSet Figures precedence of attributes <ImageView style="@style/Button.Save" android:layout_width="100dp"
android:layout_height="100dp" android:src=“@drawable/ic_done" />
LayoutInflater#inflate() B. AttributeSet Figures precedence of attributes <ImageView style="@style/Button.Save" android:layout_width="100dp"
android:layout_height="100dp" android:src=“@drawable/ic_done" />
LayoutInflater#inflate() B. AttributeSet Figures precedence of attributes <style name="Button.Save"> <item
name="android:layout_width">200dp</item> <item name="android:layout_height">200dp</item> </style>
LayoutInflater#inflate() B. AttributeSet Figures precedence of attributes <ImageView style="@style/Button.Save" android:layout_width="100dp"
android:layout_height="100dp" android:src=“@drawable/ic_done" />
Finding a View’s source Creating the View object using Reflection
LayoutInflater#inflate() C. Creating View Objects
Finding a View’s source Creating the View object using Reflection
LayoutInflater#inflate() C. Creating View Objects
Black magic Slow Reflection?
Delegate creation to “Factories” Instantiate View by itself (if #1
fails) Creating View Objects
Delegate creation to “Factories” Instantiate View by itself (if #1
fails) context.getClassLoader().loadClass(); Creating View Objects
Delegate creation to “Factories” Instantiate View by itself a) Custom
View b) Framework View Creating View Objects
a) Custom View: <android.support.v7.widget.RecyclerView android:layout_width="match_parent" android:layout_height=“match_parent" /> Creating View Objects
a) Custom View: Class<RecyclerView> clazz = ClassLoader#loadClass( "android.support.v7.widget.RecyclerView" ); RecyclerView
view = clazz.getConstructor().newInstance(); Creating View Objects
a) Framework View: <TextView android:layout_width="match_parent" android:layout_height="match_parent" /> Creating View Objects
a) Custom View: Class<TextView> clazz = ClassLoader#loadClass( "TextView" ); Creating
View Objects
a) Custom View: Class<TextView> clazz = ClassLoader#loadClass( "android.widget.TextView" ); Creating
View Objects
a) Custom View: Class<TextView> clazz = ClassLoader#loadClass( "android.widget.TextView" ); TextView
view = clazz.getConstructor().newInstance(); Creating View Objects
Delegate creation to “Factories” Instantiate View by itself Creating View
Objects
LayoutInflater Factories
Installing a Factory @Override protected void onCreate(Bundle savedState) { getLayoutInflater().setFactory2(...);
super.onCreate(savedState); }
Common Factories a) Activity public class Activity extends ContextThemeWrapper implements
LayoutInflater.Factory2 { }
Common Factories a) Activity
Common Factories a) Activity <LinearLayout> <fragment android:name="is.uncommon.ShinyFragment" android:layout_width="match_parent" android:layout_height="match_parent" />
</LinearLayout>
Common Factories a) Activity <LinearLayout> <fragment android:name="is.uncommon.ShinyFragment" android:layout_width="match_parent" android:layout_height="match_parent" />
</LinearLayout>
Common Factories b) AppCompat Continued in Part 2.
Part 2, Hooking into LayoutInflater
example, AppCompat How it back-ports material design to pre-Lollipop devices
android:theme
AppCompat Kitkat
AppCompat Kitkat
AppCompat <Button android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/custom_btn" /> custom_btn.xml <selector> @drawable/custom_btn_normal @drawable/custom_btn_focussed
@drawable/custom_btn_pressed </selector>
AppCompat <Button android:layout_width="match_parent" android:layout_height="match_parent" android:theme="@style/CustomButtonTheme" /> styles.xml <style name="CustomButtonTheme"> <item
name=“colorButtonNormal”>#09F</item> <item name=“colorControlHighlight">#07F</item> </style>
example, AppCompat AppCompatActivity @Override protected void onCreate(Bundle savedState) { installViewFactory();
... }
example, AppCompat AppCompatViewInflater.java implements LayoutInflater.Factory2 { ... }
example, AppCompat AppCompatViewInflater.java public View onCreateView(String viewName, ...) { if
("TextView".equals(viewName) { return new AppCompatTextView(); } ... }
example, AppCompat
example, Calligraphy How it applies custom fonts without using any
custom Views. <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" fontPath="fonts/Roboto-Bold.ttf" />
example, Calligraphy class CalligraphyLayoutInflater extends LayoutInflater { ... }
example, Calligraphy @Override View onCreateView(String name, AttributeSet) { View view
= super.onCreateView(...); if (view instanceOf TextView) { applyTypeface((TextView) view); } return view; }
example, Calligraphy @Override View onCreateView(String name, AttributeSet) { View view
= super.onCreateView(...); if (view instanceOf TextView) { applyTypeface((TextView) view); } return view; }
What if… We could do this? <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" formatter="IndianRupees"
/>
What if… We could do this? <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" formatter="IndianRupees"
/> 250000
What if… We could do this? <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" formatter="IndianRupees"
/> Ũ2,50,000
What if… Or this? <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" formatter="CreditCardNumber" />
What if… Or this? <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" formatter="CreditCardNumber" /> 4652
3700 0055 5032
What if… Or this? <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" formatter="CreditCardNumber" /> 3400
123456 000032
What if… Or maybe this? <FrameLayout android:layout_width="wrap_content" android:layout_height=“wrap_content" paddings="16dp 20dp"
/>
WHAT IF I TOLD YOU IT’S POSSIBLE TO DO THAT?
Introducing, Balloon!
Balloon interface BalloonAttributeListener { void onApplyAttribute( View view, int attributeResId,
Object attributeValue ); }
Application#onCreate() Balloon.config() .registerAttr(R.attr.formatter, FormatterAttrListener) .build(); Balloon
Application#onCreate() Balloon.config() .registerAttr(R.attr.formatter, FormatterAttrListener) .build(); Balloon
Application#onCreate() Balloon.config() .registerAttr(R.attr.formatter, FormatterAttrListener) .build(); Balloon
Balloon class FormatterAttrListener implements BalloonAttributeListener <> { @Override void onApplyAttribute(EditText
view, int attrResId, String attrValue) { if ("IndianRupees".equals(attrValue)) { // Add rupee symbol and format digits } } }
Pros Composition > Inheritance Can be used for multiple types
of Views Quick
Cons “Experimental” No layout preview in Android Studio
Working class BalloonLayoutInflater extends LayoutInflater { ... }
Challenges Activity getLayoutInflater() -> return LayoutInflater
Challenges Activity getLayoutInflater() -> return LayoutInflater -> return BalloonLayoutInflater
Challenges public class BalloonContext extends Context { ... }
Challenges Activity @Override void attachBaseContext(Context base) { super.attachBaseContext(BalloonContext.wrap(base)); }
Challenges Activity @Override void attachBaseContext(Context base) { super.attachBaseContext(BalloonContext.wrap(base)); }
Challenges BalloonContext @Override Object getSystemService(String name) { if (LAYOUT_INFLATER_SERVICE.equals(name)) {
return new BalloonLayoutInflater(); } return super.getSystemService(name); }
Challenges BalloonContext @Override Object getSystemService(String name) { if (LAYOUT_INFLATER_SERVICE.equals(name)) {
return new BalloonLayoutInflater(); } return super.getSystemService(name); }
Challenges Activity getLayoutInflater() -> return BalloonLayoutInflater
saket.me/droidcon
Learnings Layout inflation is a slow process. Complex layouts can
affect an Activity’s startup time.
Learnings Why non-framework Views require their fully qualified names in
XML whereas framework Views don’t. <is.uncommon.FancyCustomView /> vs. <TextView />
That’s all folks!
Uncommon hello @ uncommon.is
Questions?
More Decks by Saket Narayan
See All by Saket Narayan
IllegalStateException: Can not perform this action after onSaveInstanceState
saketme
5
660
Building offline first apps
saketme
1
280
Other Decks in Programming
See All in Programming
Performance Optimization With LLMs
xleitix
0
250
Railsバージョンを4倍にした話
optim
0
1k
現場と育てるRailsモデリング 〜Spreadsheetから始めたモデル設計〜
siroemk
2
1.2k
Modernizing iOS Apps
seyfoyun
0
150
React Native経験者が Flutterを30⽇間触って驚いたこと
3saito
0
170
graphql-ruby を Spinel で速くしようとした話
mtsmfm
0
140
仕様駆動開発入門 (何を作るかを先に決めて渡す) | 目指せ Kiro マスター 05
inariku
PRO
2
120
Zero-Tap Sign-In対応、結局何をすればいいの?
mitohato14
0
2k
Lambda durable functionsでHuman in the Loopを楽に…楽に……
har1101
2
300
Engineering Biometric UX Across Android Versions | DroidKnights 2026
ryunen344
1
190
作れるエンジニアから、価値を届けるエンジニアへ
ryunakayama
1
260
学びを記事・スライド・Xへ高速展開する― AI-assisted Learning Loopで回すコンテンツ生成術
ochtum
0
210
Featured
See All Featured
How to Build an AI Search Optimization Roadmap - Criteria and Steps to Take #SEOIRL
aleyda
1
2.2k
The State of eCommerce SEO: How to Win in Today's Products SERPs - #SEOweek
aleyda
2
12k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
250
1.3M
brightonSEO & MeasureFest 2025 - Winning Strategies for Black Friday CRO & PPC - Christian Goodrich
cargoodrich
3
890
AI: The stuff that nobody shows you
jnunemaker
PRO
11
1.3k
Become a Pro
speakerdeck
PRO
31
6.4k
Chasing Engaging Ingredients in Design
codingconduct
0
390
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
660
New Earth Scene 8
popppiees
5
2.8k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
4 Signs Your Business is Dying
shpigford
187
23k
The Curse of the Amulet
leimatthew05
4
17k