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
個人開発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.6k
What are AtCoder and competitive programming
kirimin
0
10k
バーチャル男声幼女プログラマーとして活動した1年間の振り返り
kirimin
0
1.1k
アプリエンジニアでも神絵師になりたい!
kirimin
4
5.5k
Watashi ni Kotlin ga maiorita
kirimin
0
610
NEMのAPIとモザイクであそぼう
kirimin
0
420
はじめようきれいなコード
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
AIペネトレーションテスト・ セキュリティ検証「AgenticSec」紹介資料
laysakura
2
7.5k
Comment regagner la souveraineté de vos données tout en étant payé grâce à Nostr !
rlifchitz
0
200
IaC コードを資産へ:AWS CDK 社内ライブラリと横断展開 / aws-summit-japan-2026
gotok365
10
1.6k
元銀行員がAIだけでアプリを量産!「バイブコーディング実演セミナー 」
tatsuya1970
0
110
【Snowflake Summit 2026 Recap!!】Snowflake Summit Deep Dive: Security & Governance
civitaspo
1
310
クラウドファンディング版StackChan 3体(4体)をインタラクティブな体験型作品にして展示もした話 / スタックチャンお誕生日会2026
you
PRO
0
180
LayerX コーポレートエンジニアリング室におけるサプライチェーンセキュリティへの取り組み / Supply Chain Security at LayerX Corporate Engineering
yuyatakeyama
3
840
【FinOps】データドリブンな意思決定を目指して
z63d
0
360
AIAU_UMEMOGU_ninomiya_slide
ninomiya_ii
0
260
When Platform Engineering Meets GenAI
sucitw
0
170
「軸足」は 固定しなくていい - 熱量と強みで描く、しなやかなキャリアの形
kakehashi
PRO
1
270
WebGIS AI Agentの紹介
_shimizu
0
560
Featured
See All Featured
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
860
Ten Tips & Tricks for a 🌱 transition
stuffmc
0
140
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
2
220
Making the Leap to Tech Lead
cromwellryan
135
9.9k
世界の人気アプリ100個を分析して見えたペイウォール設計の心得
akihiro_kokubo
PRO
72
40k
Leadership Guide Workshop - DevTernity 2021
reverentgeek
1
310
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
450
4 Signs Your Business is Dying
shpigford
187
22k
Building a Scalable Design System with Sketch
lauravandoore
463
34k
The Pragmatic Product Professional
lauravandoore
37
7.3k
Unsuck your backbone
ammeep
672
58k
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
1
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
誰か業務で使った実績 でっち上げてくれ!!!!
ご清聴ありがとうございました!