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
React改造してみた
tsukina_7mochi
0
160
国際カードブランドルール変更に伴うクレジットカード決済取引仕様変更について
k1style
0
210
AWSセキュリティで活用するAI機能
cmusudakeisuke
1
280
Refining Active Record
shugo
0
240
Microsoft のサポート ライフサイクルを理解する
murachiakira
PRO
0
160
導入から定着へ ~コーディングエージェントを日常業務に組み込む実践知~
yukisakai1225
0
220
日本AIベンチャーレポート2026
kentarofujii
0
220
「Learning Outcome」を書きたくない私が、Learning Outcomeと折り合いをつけるまで
mhlyc
0
210
Claude Code をローカルとサーバー上で利用した際の Bedrock 利用料をユーザー単位で一本化してみる
ohorig
0
140
撮るだけでは終わらない。ソニーが挑むB2Bカメラソリューション開発
sony
0
110
LambdaWebFunctionsを試してみた / exploring-lambda-web-functions
koukihosaka
1
400
Obsidian Vault Architectures
x5gtrn
PRO
0
120
Featured
See All Featured
Color Theory Basics | Prateek | Gurzu
gurzu
1
490
Are puppies a ranking factor?
jonoalderson
2
4.1k
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
0
270
The Anti-SEO Checklist Checklist. Pubcon Cyber Week
ryanjones
0
270
SERP Conf. Vienna - Web Accessibility: Optimizing for Inclusivity and SEO
sarafernandez
2
1.6k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
360
31k
Java REST API Framework Comparison - PWX 2021
mraible
34
9.8k
Designing for humans not robots
tammielis
254
26k
Mind Mapping
helmedeiros
1
410
Navigating Weather and Climate Data
rabernat
0
560
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
1.1k
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.8k
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
誰か業務で使った実績 でっち上げてくれ!!!!
ご清聴ありがとうございました!