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
個人開発AndroidアプリをKotlinにガチ移行してみた話
Search
きりみん
June 05, 2015
Technology
7.9k
9
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
個人開発AndroidアプリをKotlinにガチ移行してみた話
きりみん
June 05, 2015
More Decks by きりみん
See All by きりみん
AndroidエンジニアがRailsにチャレンジしてる理由
kirimin
1
1.7k
What are AtCoder and competitive programming
kirimin
0
10k
バーチャル男声幼女プログラマーとして活動した1年間の振り返り
kirimin
0
1.2k
アプリエンジニアでも神絵師になりたい!
kirimin
4
5.6k
Watashi ni Kotlin ga maiorita
kirimin
0
610
NEMのAPIとモザイクであそぼう
kirimin
0
430
はじめようきれいなコード
kirimin
8
3.2k
Material Components for Android触ってみる
kirimin
7
2.1k
[社内LT]あたらしいMaterial Design
kirimin
1
1.8k
Other Decks in Technology
See All in Technology
What Is JetBrains Air
x5gtrn
PRO
0
170
CloudWatch Logsのコスト最適化:どこまでAIに任せてどこから人間が承認すべきか
yama3133
0
180
[EMNLP26] RIGEL: Self-Distilled Score Adaptation for Image and Video Captioning Evaluation
keio_smilab
PRO
0
120
クラウドサインを止めずに Nuxt へ 次の10年のために先に決めたこと
bengo4com
1
110
AI × アーキテクト 第1・2章|生成AIの課題とアーキテクトの素養
daidaidai
1
240
Practical ransomware detection on macOS (via maths, not AI)
patrickwardle
0
110
撮るだけでは終わらない。ソニーが挑むB2Bカメラソリューション開発
sony
0
110
「エーアイ」をバズワードにしないために RPA 導入経験と Kiro 上での Claude モデル利用経験から
kazzpapa3
0
120
外国人エンジニアがVueプロトタイプで仕様を合わせている話 / Vue Fes Japan 2026 LT
eluwing
0
140
生成AI時代、PMは事業責任者に進化するともっと面白い〜PMだからこそ事業構造を動かせる時代に〜
kakehashi
PRO
0
750
Temporal 最高!でも改めて「日付」について調べたら人類の負債すぎる件
riyaamemiya
0
230
AI時代のGraphQL
joere
3
380
Featured
See All Featured
Navigating Team Friction
lara
192
16k
KATA
mclloyd
PRO
35
16k
Technical Leadership for Architectural Decision Making
baasie
3
610
The Cult of Friendly URLs
andyhume
79
7k
From Legacy to Launchpad: Building Startup-Ready Communities
dugsong
0
360
Large-scale JavaScript Application Architecture
addyosmani
516
110k
Raft: Consensus for Rubyists
vanstee
143
7.8k
Building Adaptive Systems
keathley
44
3.3k
Music & Morning Musume
bryan
48
7.4k
HTML-Aware ERB: The Path to Reactive Rendering @ RubyCon 2026, Rimini, Italy
marcoroth
5
840
Marketing to machines
jonoalderson
1
5.9k
Visualization
eitanlees
153
17k
Transcript
個人開発Androidアプリを Kotlinにガチ移行してみた話 2015/6/5 第3回 かわいいKotlin勉強会 @kirimin
自己紹介 @kirimin • Androidアプリ開発者 (ジャバ) • エンジニア4年目 フリーランス2年目 • 現在は圧倒的当事者意識で某社の
Androidアプリ開発を手伝っています
自己紹介
None
今、Androidで Kotlinがアツい!!!!
なぜAndroidでKotlin?
なぜAndroidでKotlin?(おさらい) • AndroidではJava8が当分使えなそう • Kotlinならラムダ式もパイプラインでのリスト操作も書ける • RxAndroidとも相性が良い • Android StudioならIDEのサポートが効きすぐに使える
• 学習コストも低く、静的で安全志向な言語仕様は Androidエンジニアに丁度いい(主観) • Scalaはいろんな意味で人類にはまだ早い
KotlinでAndroid開発がしたい!!!
でも、本当に使えるのだろうか?
ならば既存アプリを全力で Kotlin化してみよう!!!
今回Kotlin化したアプリ https://play.google.com/store/apps/details?id=me.kirimin.mitsumine
mitsumine
mitsumine • 約3500行 • 54クラス • 使用しているライブラリ • RxAndroid •
Volley • ActiveAndroid • Picasso など...
やったこと • Kotlin利用準備 • JavaクラスをひたすらKotlin化 • Kotlin Android Extensionsを導入 •
もっとKotlinらしくしてみる
やったこと • Kotlin利用準備 • JavaクラスをひたすらKotlin化 • Kotlin Android Extensionsを導入 •
もっとKotlinらしくしてみる
Kotlin利用準備 • Android StudioにKotlinプラグインをインストール • build.gradleにおまじないを記述 だいたいこれだけ。 しかも.ktファイルを作るとポップアップが出てきて自動で やってくれる。
やったこと • Kotlin利用準備 • JavaクラスをひたすらKotlin化 • Kotlin Android Extensionsを導入 •
もっとKotlinらしくしてみる
JavaクラスをひたすらKotlin化 「Convert Java to Kotlin File」でひたすらポチポチ…
JavaクラスをひたすらKotlin化 「Convert Java to Kotlin File」でひたすらポチポチ… • クラス数が多いと結構だるい… (一斉変換も出来るけど) • 大抵は自動変換しただけでちゃんと動く
• 時々コンパイルエラーが出る • 時々実行時エラーが出る • 時々変な変換されて処理が消える • 1クラス変換する度にDiffって動作確認した方がハマらない(戒め)
JavaクラスをひたすらKotlin化 変換時に遭遇したエラーの思い出 • Null許容型とNull非許容型で型エラーが出てる →型に?を付けてNull許容型に変えたりして頑張ろう • overrideメソッドのsuperでエラーが出てる →super<Fragment>のようにどのスーパークラスを呼ぶのか 明示しよう •
CustomViewのコンストラクタでエラーが出てる →class xxxView: View()の()を消してsecondary constructor の構文を使おう
• Kotlin利用準備 • JavaクラスをひたすらKotlin化 • Kotlin Android Extensionsを導入 • もっとKotlinらしくしてみる
やったこと
Kotlin Android Extensionsを導入 Kotlin Android Extensionsとは • KotlinのAndroid用公式ライブラリ(プラグイン) • findViewByIdを葬り去るためのライブラリ
• Activityクラスのimport文でActivityとレイアウトファイルを紐 付けるだけでActivityにViewのプロパティを生やしてくれる • Butter Knifeの@InjectViewすら必要ない版のようなイメージ • 手軽に使えてめちゃくちゃ便利
Kotlin Android Extensionsを導入 import kotlinx.android.synthetic.<layout>.* ActivityやFramentにレイアウトファイルを紐付ける。 userNameTextView.setText(“test”); Activityのプロパティになるのでそのまま参照出来る。 getView().userNameTextView.setText(“test”); Fragmentの場合はgetView()で取得出来るルートのViewに生える。
• Kotlin利用準備 • JavaクラスをひたすらKotlin化 • Kotlin Android Extensionsを導入 • もっとKotlinらしくしてみる
やったこと
もっとKotlinらしくしてみる 匿名クラスをラムダ式に書き換える textView.setOnClickListener(object : View.OnClickListener { override fun onClick(v: View)
{ } }) textView.setOnClickListener { v -> } ↓
もっとKotlinらしくしてみる 匿名クラスのままKotlinに変換されたRxJavaの処理も subscriptions.add(EntryInfoApi.request(RequestQueueSingleton.get(getApplicationContext()), url) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .map<EntryInfo>(EntryInfoFunc.mapToEntryInfo()) .filter(object : Func1<EntryInfo,
Boolean> { override fun call(entryInfo: EntryInfo?): Boolean? { return entryInfo == null } }) .subscribe(object : Action1<EntryInfo> { override fun call(entryInfo: EntryInfo) { countLayout.setVisibility(View.VISIBLE) titleTextView.setText(entryInfo.getTitle()) bookmarkCountTextView.setText(String.valueOf(entryInfo.getBookmarkCount())) Picasso.with(getApplicationContext()).load(entryInfo.getThumbnailUrl()).fit().into(thumbnailImageView) val adapter = EntryInfoPagerAdapter(getSupportFragmentManager()) adapter.addPage(BookmarkListFragment.newFragment(entryInfo.getBookmarkList()), getString(R.string.entry_info_all_bookmarks)) subscriptions.add(Observable.from<Bookmark>(entryInfo.getBookmarkList()) .filter(EntryInfoFunc.hasComment()) .toList() .subscribe(object : Action1<List<Bookmark>> { override fun call(commentList: List<Bookmark>) { commentCountTextView.setText(String.valueOf(commentList.size())) adapter.addPage(BookmarkListFragment.newFragment(commentList), getString(R.string.entry_info_comments)) if (AccountDAO.get() != null) { adapter.addPage(RegisterBookmarkFragment.newFragment(entryInfo.getUrl()), getString(R.string.entry_info_register_bookmark)) } viewPager.setAdapter(adapter) viewPager.setCurrentItem(1) viewPager.setOffscreenPageLimit(2) tabs.setViewPager(viewPager) } })) } }, object : Action1<Throwable> { override fun call(throwable: Throwable) { Toast.makeText(getApplicationContext(), R.string.network_error, Toast.LENGTH_SHORT).show() }
もっとKotlinらしくしてみる 全てラムダ式にしてスッキリ! subscriptions.add(EntryInfoApi.request(RequestQueueSingleton.get(getApplicationContext()), url) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .map { response ->
EntryInfoFunc.toEntryInfo(response) } .filter { entryInfo -> !entryInfo.isNullObject() } .subscribe ({ entryInfo -> countLayout.setVisibility(View.VISIBLE) titleTextView.setText(entryInfo.title) bookmarkCountTextView.setText(entryInfo.bookmarkCount.toString()) Picasso.with(getApplicationContext()).load(entryInfo.thumbnailUrl).fit().into(thumbnailImageView) val adapter = EntryInfoPagerAdapter(getSupportFragmentManager()) adapter.addPage(BookmarkListFragment.newFragment(entryInfo.bookmarkList), getString(R.string.entry_info_all_bookmarks)) subscriptions.add(Observable.from<Bookmark>(entryInfo.bookmarkList) .filter { bookmark -> EntryInfoFunc.hasComment(bookmark) } .toList() .subscribe { commentList -> commentCountTextView.setText(commentList.size().toString()) adapter.addPage(BookmarkListFragment.newFragment(commentList), getString(R.string.entry_info_comments)) AccountDAO.get()?.let { adapter.addPage(RegisterBookmarkFragment.newFragment(entryInfo.url), getString(R.string.entry_info_register_bookmark)) } commentsViewPager.setAdapter(adapter) commentsViewPager.setCurrentItem(1) commentsViewPager.setOffscreenPageLimit(2) tabs.setViewPager(commentsViewPager) }) }, { Toast.makeText(getApplicationContext(), R.string.network_error, Toast.LENGTH_SHORT).show() })
もっとKotlinらしくしてみる リスト操作を高階関数に書き換える for (i in list) { if (i %
2 == 0) { System.out.print(i) } } list.filter { i -> i % 2 == 0 } .forEach { i -> System.out.print(i) } ↓
もっとKotlinらしくしてみる Callback用の自前Interface(trait)も public trait TestCallback { public fun onSuccess(callback: Int)
} public fun request(callback: TestCallback) { callback.onSuccess(200) } // 呼び出し元 test.request(object : Test.TestCallback { override fun onSuccess(callback: Int) { } })
もっとKotlinらしくしてみる 高階関数で直接処理を受け取ればシンプルに出来ます public fun request(onSuccess: (callback: Int) -> Unit) {
onSuccess(200) } // 呼び出し元 test.request { callback -> }
まとめ
まとめ • Kotlin置換+αの対応だけで3500行→3000行くらいにコード をスリム化! • Javaで設計されたコードの移行はわりと大変だった (単純置換だけだとかえって読みにくいコードになるかも) • とはいえAndroidアプリの開発をガッツリKotlinでやる事自体 の不便さや辛さはほとんど感じなかった
(ライブラリなどもそのまま使えたよ) • むしろ一度Kotlinを味わうとAndroidJavaでリスナーや リスト操作を書くのが辛くなる
まとめ • 個人開発の新規アプリや期間限定の出し切りアプリなどであれ ばKotlinは現実的な選択肢では • 個人開発の既存アプリを書き換えるべきかはモチベーション 次第だけどメリットは十分あると思う • 業務で導入する場合、標準じゃない技術に依存するリスクを メリットが上回るかは………
まとめ • 詳しい知見はコードをご確認ください https://github.com/kirimin/mitsumine
誰か業務で使った実績 でっち上げてくれ!!!!
ご清聴ありがとうございました!