こんにちは。
dely の開発部でクラシルの Android を担当している tummy です。 2019 年 12 月から dely に入社して、たくさんキャッチアップしながら初めての施策を実装しています。ついていくので精一杯です。。笑
この記事は「dely Advent Calendar 2019」の 20 日目の記事になります。
昨日は同じ Android チームの kenzo による「エンジニアは体が資本でしょ。と思って始めた習慣とその続け方」という記事でした。 自分は三日坊主になることが多いので、次になにか継続しようと思ったときはアドバイスをもらおうと思います。
今回は、新しいプロジェクトに入った際のキャッチアップ時に行っている、担当する Android アプリの中身を「なるべく早く」「ざっくりと」把握するためのコードリーディング方法を紹介できればと思います :)
目的
何がどこにあってどう使われているか、を粗方把握している 状態を目指します。この状態になっていれば、とりあえず該当箇所を見に行けるため一次調査が自分で行えると考えているからです。
まずやること
- build.gradle で何が入っているのか見る
- デバッグ周りを調べる
- package 構成を見る
以上の 3 つです。
まず、build.gradle を見ます。ライブラリの一覧が記述されているので通信ライブラリや Android SDK まわりで使っているものを確認できます。また、flavor や Lint の設定なども記述されているため、手元で開発するときの環境が把握できます。
その後、デバッグまわりを調べてデバッグメニューが実装されているかどうか、Stetho やこのあとも紹介する Hyperion などのデバッグツールが入っていないか見ます。
そして、package 構成を見に行きます。 ここまでやったあとにコードを読みに行きます。
コードを読む方法
PR を見に行く
コードを読めばなんとなくやっていることはわかりますが、「なぜこういう実装になっているのか?」という箇所を発見した場合、プルリクに書いてあればそれを元に理解することができる可能性があります。Find Pull Request という Intellij プラグインがあるのでそれを活用します。
GitHub 等を使ってプルリクベースで開発していることが前提になりますが、こういった情報も概要を掴む上で助けになってくれるはずです。
Android Studio の機能フル活用
ショートカットをたくさん使うのはもちろんですが、他に特に便利なものを紹介します。
Breakpoint にひっかけて Frames を見る
ブレークポイントを任意の場所(例えばどこから遷移してくるのか知りたい Activity の onCreate)に置き、Debugger を起動してブレークポイントの場所を通ると Debug のビューが開くと思います。 そこに Frames という欄があり、アプリ起動からそのブレークポイントに至るまでが表示されています。
上記の場合、「MainActivity の initListener
メソッドで onClick が呼ばれ、SecondActivity の Companion Object 内にある createIntent が呼ばれた」と読むことができます。
このことから、MainActivity から SecondActivity に飛ぶ際の Intent が SecondActivity 内のメソッドで作られている事がわかります。
Layout Inspector
実行中のアプリのレイアウトがどういった構造になっているか確認することができます。 Tools > Layout Inspector から起動できます。
2 つ以上 Activity を開いていれば、起動時にダイアログが表示されて Activity のクラス名が判明します。実機で触ってみるフェーズにおいて、こちらを併用しながらコードを読んでいくと捗るかと思います。
※ Android Studio 4.0 から使える Live Layout Inspector もあるとより便利ですね!
Hyperion-android の活用
hyperion-android というデバッグライブラリがあり、Timber の中身やクラッシュログを確認することができます。またこのライブラリのサードパーティで、任意のアイテムを追加できるものがあり、今回はそちらを活用します。
どのクラスにいるかを Toast で出す
Application クラス内で以下のように実装します。
override fun onCreate() { super.onCreate() val listener = object : ActivityLifecycleCallbacks { private var activityName: String? = null override fun onActivityPaused(activity: Activity) { } override fun onActivityStarted(activity: Activity) { } override fun onActivityDestroyed(activity: Activity) { } override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) { } override fun onActivityStopped(activity: Activity) { } override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { } override fun onActivityResumed(activity: Activity) { activityName = activity.javaClass.simpleName } fun getCurrentActivityName() = activityName } registerActivityLifecycleCallbacks(listener) val item = SimpleItem.Builder("debug") .image(R.drawable.ic_launcher_foreground) .text("Show class name") .clickListener { Toast.makeText(this, listener.getCurrentActivityName(), Toast.LENGTH_LONG).show() } .build() SimpleItemHyperionPlugin.addItem(item) }
FragmentLifecycleCallbacks を使えば Fragment でも同様に取得できると思います。
まとめ
最初からすべてを把握するのは大変難しく、時間を要します。そのため、基本的な設計とメインループだけわかっていれば最初の入りとしては上出来で、他の画面等については施策やレビュー等でいじった際に理解していけば良いと考えています。 自分は Android Studio やちょっとした実装をすることでカバーしていましたが、他にこういうツールも便利ですよっていうのあったらぜひ教えて下さい!
明日は iOS エンジニアのふくさんが、「“ダーク“な2019年」というタイトルでお届けします。
さいごに
dely では Android エンジニアを絶賛募集中です、ご興味あればこちらのリンクからお気軽にエントリーください!
開発チームについて詳しく知りたい方はこちらから 🙆