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
Kotin Android Extensionsの中身とこれから
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
RyotaMurohoshi
November 09, 2017
Technology
910
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Kotin Android Extensionsの中身とこれから
2017/11/09 第7回 Kotlin勉強会 @SanSan
の
むろほしりょうた(@RyotaMurohoshi)
の資料です。
RyotaMurohoshi
November 09, 2017
More Decks by RyotaMurohoshi
See All by RyotaMurohoshi
Tilemapのアップデートについて
ryotamurohoshi
0
96
Unityの合同同人誌や合同商業誌を書いてる僕は感想やレビューや評価が欲しい
ryotamurohoshi
0
630
Unity 2021.1での Unityパッケージの名称変更について
ryotamurohoshi
0
900
Odin Validationはいいぞ!
ryotamurohoshi
2
1.1k
Tilemapはいいぞ!2020 〜すごいぞ、プロジェクト専用拡張Brush〜
ryotamurohoshi
0
2.6k
Unityでも、新しいC#
ryotamurohoshi
0
1.5k
Riderはいいぞ!
ryotamurohoshi
1
3.8k
Riderのススメ〜俺はRiderここが好き〜
ryotamurohoshi
1
2.8k
Unity開発者に伝えたい.NETのこと
ryotamurohoshi
4
38k
Other Decks in Technology
See All in Technology
[2026-09-11]SREは誰のもの?運用エンジニアが始める 「SRE領域への越境」とチームの進化の軌跡 〜Road to NEXT CRE
tosite
0
220
Claude Codeを「使うほど育つ」AI秘書にするノウハウ
minorun365
PRO
13
8k
Genieを崇めよ
kameitomohiro
0
120
Reactの設計論
uhyo
22
12k
What the customer really needed
kawaguti
PRO
1
120
【技術的負債conf】事業成長に伴う技術的負債の説明責任とAIによるモニタリング、認知的負債について
i35_267
2
930
コスト最適化の「めんどくさい」を AWS FinOps Agent でチョット楽にする
classmethod_kaz
0
340
Sigmaユーザーのための有用リソース一挙公開 & Sigmaで使えるMCP #sigma_ucj /useful-resources-for-sigma-computing-users-and-mcps-with-sigma
shinyaa31
0
230
omasushiというライブラリを作った
polidog
PRO
0
220
空間オーディオで過去の 自分(ゴースト)と競うランニング 〜HealthKitのルートを足音に変える実装〜
nao_randd
0
170
Sigmaで作る業務アプリ
kazushiro_honma
0
140
越境するなら専門用語を使うな高校校歌 / If you wanna cross border, you shouldn't use jargon
vtryo
0
130
Featured
See All Featured
How to Ace a Technical Interview
jacobian
281
24k
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
3
1.2k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
232
55k
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
850
Google's AI Overviews - The New Search
badams
0
1.6k
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
430
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
2.1k
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
380
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
From Legacy to Launchpad: Building Startup-Ready Communities
dugsong
0
330
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
23k
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
1
2.9k
Transcript
Ko#n Android Extensionsͷதͱ͜Ε͔Β @RyotaMurohoshi 2017/11/09 ୈ7ճ Kotlinษڧձ @SanSan
Kotlin Android Extensions ͍ͬͯΔਓʁ
ͬͺΓDataBindingͰ͔͢ʁ ͦΕͱankoͰ͔͢ʁ
Kotlin Android Extensions ɺ͖Ͱ͢
ɹࣗݾհ @RyotaMurohoshi
࠷ۙձࣾͰɺKotlinຊಡॻձΛ࢝Ί·ͨ͠
Tools > Kotlin > Show Kotlin Bytecode > Decompile ͜ΕΛԿΑΓઌʹڭ͑ͯ͋͛Δͱ͍͍ͱࢥ͏ʂ
ʮKo#n Android Extensionsͷ தͱ͜Ε͔Βʯ ʹ͍ͭͯ͠·͢ Kotlin 1.1.51ʹͯ
Kotlin Android Extensions ʹ͍͓ͭͯ͞Β͍
ViewͷΠϯελϯεʹ؆୯ʹ ΞΫηεͰ͖Δͭ
gadleͷதͰ͜͏ॻ͘ (͍ͯ͏͔σϑΥϧτͰೖ͍ͬͯΔ) apply plugin: 'kotlin-android-extensions'
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.teammurosta.MainActivity"> <TextView
android:id="@+id/textView" android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_centerInParent="true" /> </RelativeLayout>
ίʔυͰtextViewͱ͍͏໊લͰ TextViewܕͱͯ͠ΞΫηεͰ͖Δ class MainActivity : Activity() { override fun onCreate(savedInstanceState:
Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // TextViewܕͷtextView͕ʂ textView.text = "Hello Activity" } }
// TextViewܕͷtextView͕ʂ textView.text = "Hello Activity"
؆୯Ͱ͠ΐʂ ศརͰ͠ΐʂ
தΈͯΈ·͠ΐ͏
Tools > Kotlin > Show Kotlin Bytecode > Decompile
class MainActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // TextViewܕͷtextView͕ʂ textView.text = "Hello Activity" } }
/* ུ */ public final class MainActivity extends AppCompatActivity {
private HashMap _$_findViewCache; protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.setContentView(2131296283); ((TextView)this._$_findCachedViewById(id.textView)).setText((CharSequence)"Hello Activity"); } public View _$_findCachedViewById(int var1) { if(this._$_findViewCache == null) { this._$_findViewCache = new HashMap(); } View var2 = (View)this._$_findViewCache.get(Integer.valueOf(var1)); if(var2 == null) { var2 = this.findViewById(var1); this._$_findViewCache.put(Integer.valueOf(var1), var2); } return var2; } public void _$_clearFindViewByIdCache() { if(this._$_findViewCache != null) { this._$_findViewCache.clear(); } } }
/* ུ */ public final class MainActivity extends AppCompatActivity {
private HashMap _$_findViewCache; protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.setContentView(2131296283); ((TextView)this._$_findCachedViewById(id.textView)) .setText((CharSequence)"Hello Activity"); } public View _$_findCachedViewById(int var1) { if(this._$_findViewCache == null) { this._$_findViewCache = new HashMap(); } View var2 = (View)this._$_findViewCache.get(Integer.valueOf(var1)); if(var2 == null) { var2 = this.findViewById(var1); this._$_findViewCache.put(Integer.valueOf(var1), var2); } return var2; } /* ུ */
σίϯύΠϧͯ͠ΈΔͱ • _$_findViewCacheͱ͍͏HashMapΛϑΟʔϧυͱͯ࣋ͭ͠ • _$_findCachedViewByIdϝιουɺ • Ҿʹͱͬͨid͕HashMapʹ͋ΕͦΕΛฦ͠ • ͳ͚Ε୳ࡧɺHashMapʹೖΕͨޙɺͦΕΛฦ͢ _$_findViewCache_findCachedViewByIdɺKotlinͰίʔυͰ͔͚ͳ͍ɻཁʮ``ʯ
/* ུ */ public final class MainActivity extends AppCompatActivity {
private HashMap _$_findViewCache; protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.setContentView(2131296283); ((TextView)this._$_findCachedViewById(id.textView)) .setText((CharSequence)"Hello Activity"); } public View _$_findCachedViewById(int var1) { if(this._$_findViewCache == null) { this._$_findViewCache = new HashMap(); } View var2 = (View)this._$_findViewCache.get(Integer.valueOf(var1)); if(var2 == null) { var2 = this.findViewById(var1); this._$_findViewCache.put(Integer.valueOf(var1), var2); } return var2; } /* ུ */
͜Μͳײ͡ͷ֦ுϓϩύςΟ͕ੜ͑ΔΘ͚Ͱͳ͍ʂ // ͜Μͳײ͡͡Όͳ͍ʂ // Ωϟογϡػߏ͋ΔΑ val MainActivity.textView : TextView get()
= findViewById(R.id.textView)
FragmentͰKotlin Android Extensions͑·͢ FragmentͰಉ͡Α͏ʹHashMapͰͷΩϟογϡػߏʂ
֦ுؔͷதͰʂ package com.teammurosta import kotlinx.android.synthetic.main.activity_main.* fun MainActivity.updateText(text: String) { this.textView.text
= text }
import android.os.Bundle import android.support.v7.app.AppCompatActivity class MainActivity : AppCompatActivity() { override
fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) updateText("Hello") } }
// ֦ுؔͷσίϯύΠϧ݁Ռ public final class MainActivityExtensionsKt { public static final
void updateText(@NotNull MainActivity $receiver, @NotNull String text) { Intrinsics.checkParameterIsNotNull($receiver, "$receiver"); Intrinsics.checkParameterIsNotNull(text, "text"); ((TextView)$receiver._$_findCachedViewById(id.textView)).setText((CharSequence)text); } }
// MainActivityͷσίϯύΠϧ݁Ռ public final class MainActivity extends AppCompatActivity { private
HashMap _$_findViewCache; protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.setContentView(2131296283); MainActivityExtensionsKt.updateText(this, "Hello"); } public View _$_findCachedViewById(int var1) { if(this._$_findViewCache == null) { this._$_findViewCache = new HashMap(); } View var2 = (View)this._$_findViewCache.get(Integer.valueOf(var1)); if(var2 == null) { var2 = this.findViewById(var1); this._$_findViewCache.put(Integer.valueOf(var1), var2); } return var2; } public void _$_clearFindViewByIdCache() { if(this._$_findViewCache != null) { this._$_findViewCache.clear(); } } }
Կ͕ԿͰΩϟογϡ͢ΔΘ͚͡Όͳ͍
֦ுؔͷதͰʂMainAc'vity -> Ac'vityʹมߋʂ package com.teammurosta import kotlinx.android.synthetic.main.activity_main.* fun Activity.updateText(text: String)
{ this.textView.text = text }
// ֦ுؔͷσίϯύΠϧ݁Ռ public final class MainActivityExtensionsKt { public static final
void updateText(@NotNull Activity $receiver, @NotNull String text) { Intrinsics.checkParameterIsNotNull($receiver, "$receiver"); Intrinsics.checkParameterIsNotNull(text, "text"); ((TextView)$receiver.findViewById(id.textView)).setText((CharSequence)text); } }
android.app.Ac+vityΫϥε android.support.v7.app.AppCompatAc2vityΫϥεɺ android.support.v4.app.FragmentΫϥεΛ֦ுͨ͠߹ɺ ී௨ʹfindViewByIdΛݺͿ
ViewHolderͰͷ׆༻ྫ
Kotlin Android Extensions ΛͬͯBind import kotlinx.android.synthetic.main.listitem_product.view.* class ProductViewHolder(containerView: View) :
RecyclerView.ViewHolder(containerView) { fun bind(product: Product) { itemView.nameTextView.text = product.name itemView.idTextView.text = product.id } }
σίϯύΠϧ݁ՌΛΈΔͱΩϟογϡ͍ͯ͠ͳ͍ public final class ProductViewHolder extends ViewHolder { public final
void bind(@NotNull Product product) { Intrinsics.checkParameterIsNotNull(product, "product"); ((TextView)this.itemView.findViewById(id.nameTextView)).setText((CharSequence)product.getName()); ((TextView)this.itemView.findViewById(id.idTextView)).setText((CharSequence)product.getId()); } public ProductViewHolder(@NotNull View containerView) { Intrinsics.checkParameterIsNotNull(containerView, "containerView"); super(containerView); } }
͔͜͜Βઌɺ͜Ε͔Βͷ
Kotlin 1.1.4ͰύϫʔΞοϓ experimental͚ͩͲ androidExtensions { experimental = true }
1. Ωϟογϡઓུ
@ContainerOp,ons
ࠓ·ͰΩϟογϡHashMapͷΈ ʮSparseArrayʯͱʮΩϟογϡ͠ͳ͍ʯ ΛબΔΑ͏ʹͳͬͨʂ
// ↓Ξϊςʔγϣϯ @ContainerOptions(CacheImplementation.SPARSE_ARRAY) class MainActivity : Activity() { override fun
onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) textView.text = "Hello" } }
public final class MainActivity extends Activity { private SparseArray _$_findViewCache;
protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); ((TextView)this._$_findCachedViewById(id.textView)).setText((CharSequence)"Hello"); } public View _$_findCachedViewById(int var1) { if(this._$_findViewCache == null) { this._$_findViewCache = new SparseArray(); } View var2 = (View)this._$_findViewCache.get(var1); if(var2 == null) { var2 = this.findViewById(var1); this._$_findViewCache.put(var1, var2); } return var2; } public void _$_clearFindViewByIdCache() { if(this._$_findViewCache != null) { this._$_findViewCache.clear(); } } }
// ↓Ξϊςʔγϣϯ @ContainerOptions(CacheImplementation.NO_CACHE) class MainActivity : Activity() { override fun
onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) textView.text = "Hello" } }
public final class MainActivity extends Activity { protected void onCreate(@Nullable
Bundle savedInstanceState) { super.onCreate(savedInstanceState); ((TextView)this.findViewById(id.textView)).setText((CharSequence)"Hello"); } }
ҰׅมߋͰ͖Δ ະυΩϡϝϯτԽͰ༷มߋ͢Δ͔͠Εͳ͍͚Ͳ
app/build.gradleͰઃఆ androidExtensions { experimental = true defaultCacheImplementation = "sparse_array" //
hash_map or none }
ΩϟογϡʹSparseArrayɺͬͨ΄͏͕͍͍ͷʁ
Do we need to change the default cache implementa3on to
SparseArray? Looks like no, because "It is generally slower than a tradi8onal HashMap, since lookups require a binary search and adds and removes require inser8ng and dele8ng entries in the array" Kotlin KEEPΑΓ
2. ViewHolderରԠ
Kotlin Android Extensions ΛͬͯBind import kotlinx.android.synthetic.main.listitem_product.view.* class ProductViewHolder(containerView: View) :
RecyclerView.ViewHolder(containerView) { fun bind(product: Product) { itemView.nameTextView.text = product.name itemView.idTextView.text = product.id } }
σίϯύΠϧ݁ՌΛΈΔͱΩϟογϡ͍ͯ͠ͳ͍ public final class ProductViewHolder extends ViewHolder { public final
void bind(@NotNull Product product) { Intrinsics.checkParameterIsNotNull(product, "product"); ((TextView)this.itemView.findViewById(id.nameTextView)).setText((CharSequence)product.getName()); ((TextView)this.itemView.findViewById(id.idTextView)).setText((CharSequence)product.getId()); } public ProductViewHolder(@NotNull View containerView) { Intrinsics.checkParameterIsNotNull(containerView, "containerView"); super(containerView); } }
Ac#vityFragmentͷαϒΫϥεΈ͍ͨʹ Ωϟογϡ͢Δʹʁ
LayoutContainer
LayoutContainerΛ࣮͢Δ import kotlinx.android.synthetic.main.listitem_product.* class ProductViewHolder(override val containerView: View /*<=
*/) : RecyclerView.ViewHolder(containerView), LayoutContainer /*<= */ { fun bind(product: Product) { // nameTextView.text = product.name idTextView.text = product.id } }
Ωϟογϡ͢ΔΑ͏ʹʂ public final class ProductViewHolder extends ViewHolder implements LayoutContainer {
@NotNull private final View containerView; private HashMap _$_findViewCache; public final void bind(@NotNull Product product) { Intrinsics.checkParameterIsNotNull(product, "product"); ((TextView)this._$_findCachedViewById(id.nameTextView)).setText((CharSequence)product.getName()); ((TextView)this._$_findCachedViewById(id.idTextView)).setText((CharSequence)product.getId()); } @NotNull public View getContainerView() { return this.containerView; } public ProductViewHolder(@NotNull View containerView) { Intrinsics.checkParameterIsNotNull(containerView, "containerView"); super(containerView); this.containerView = containerView; } public View _$_findCachedViewById(int var1) { if(this._$_findViewCache == null) { this._$_findViewCache = new SparseArray(); } View var2 = (View)this._$_findViewCache.get(var1); if(var2 == null) { View var10000 = this.getContainerView(); if(var10000 == null) { return null; } var2 = var10000.findViewById(var1); this._$_findViewCache.put(var1, var2); } return var2; } public void _$_clearFindViewByIdCache() { if(this._$_findViewCache != null) { this._$_findViewCache.clear(); } } }
3. ParcelableରԠ
@Parcelize
@SuppressLint("ParcelCreator") @Parcelize data class Product(val name: String, val id: String)
: Parcelable
public final int describeContents() { return 0; } public final
void writeToParcel(@NotNull Parcel parcel, int flags) { Intrinsics.checkParameterIsNotNull(parcel, "parcel"); parcel.writeString(this.name); parcel.writeString(this.id); } public static class Creator implements android.os.Parcelable.Creator { @NotNull public final Product[] newArray(int size) { return new Product[size]; } @NotNull public final Object createFromParcel(@NotNull Parcel in) { Intrinsics.checkParameterIsNotNull(in, "in"); return new Product(in.readString(), in.readString()); } }
ͨͩɺAndroid 4ܥͷҰ෦ͷͰ Πϯετʔϧʹࣦഊ͢ΔΈ͍ͨ ͜Ε͔Βʹظʂ 4.1ͷEmulatorͰࣦഊΛ֬ೝࡁΈ
KEEPʹɺʮSealdΫϥεʹରԠΛݕ౼ʯͬͯॻ͍ͯ͋Δ ࣮ࡍ·ͩͰ͖ͳ͍Έ͍ͨʁͲ͏ͳΔͩΖ͏ʁ
ࠓޙʹظʂ
ͶɺKotlin Android Extensions ͍͍Ͱ͠ΐʂ
·ͱΊ • DataBinding͍͍͚ͲɺKotlin Android ExtensionsͶ • Parcelizeɺࠓޙʹظʂ • KEEPΈΔͷָ͍͠Αʂ
όάʁ Kotlin Android Extensions͕༗ޮʹͳͬͯͳ͍ ϓϩδΣΫͰAc#vityFragmentʹ _$_findCachedViewByIdͱ͔͕Ͱ͖͍ͯΔʁ
Ko#n Android Extensionsͷதͱ͜Ε͔Β @RyotaMurohoshi 2017/11/09 ୈ7ճ Kotlinษڧձ @SanSan