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
Kotin Android Extensionsの中身とこれから
Search
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
620
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
Amazon S3 Tablesに全部任せてみた結果——コンパクション/スナップショット管理は本当に手放せるか
shigeruoda
0
370
Bet AI Day 2026丨AIによって本質に戻るシステムリスク管理
layerx
PRO
0
870
「重なり」は迎える側がつくる ― 人もAIエージェントも歓迎するプロダクトエンジニアリング ―
go0517go
PRO
0
230
Bet AI Day 2026丨How We Bet AI: AIとともに働く場をつくる
layerx
PRO
1
2.2k
Redmine 7.0で私が開発した新機能の狙いと背景
vividtone
1
110
AI時代に、プロダクトの数だけ積み上がる所有コストをどうエンジニアリングするか / Engineering the Cost of Ownership
kzkmaeda
0
990
いま、生成AIにKaggleをどこまで 任せられるか — ROGIIコンペでの進め方とTips
k951286
3
1.4k
Nav2、Nav3 ... はたまた自作?〜 作って理解する Nav3 の設計意図 〜 / Nav2, Nav3 ... or Build Your Own? — Understanding Nav3's design intent by building it from scratch
yanzm
0
220
[DroidKaigi 2026] Making UI specifications visible: Android UI development in the AI agent era supported by Compose Screenshot Testing and galleries
syarihu
0
570
Hub & Spoke 環境のネットワークルーティングを分解してみる
tsuyataku
1
520
enechainの内製セルフサービスプラットフォーム
hiyosi
0
100
データエンジニアリングワークショップ:Auto LoaderとSparkで学ぶデータパイプライン構築
databricksjapan
PRO
0
150
Featured
See All Featured
A Tale of Four Properties
chriscoyier
163
24k
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
840
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.2k
Heart Work Chapter 1 - Part 1
lfama
PRO
8
36k
The Illustrated Guide to Node.js - THAT Conference 2024
reverentgeek
1
470
What does AI have to do with Human Rights?
axbom
PRO
1
2.4k
We Have a Design System, Now What?
morganepeng
55
8.3k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
38
3k
The World Runs on Bad Software
bkeepers
PRO
72
12k
Side Projects
sachag
455
43k
The Power of CSS Pseudo Elements
geoffreycrofte
82
6.5k
The State of eCommerce SEO: How to Win in Today's Products SERPs - #SEOweek
aleyda
2
11k
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