今更だけど Android Studio の カスタムテンプレート機能が便利

Photo by Daniel Schludi on Unsplash

Android Architecture Components の ViewModel, LiveData の登場により、長年仕事で携わっているプロダクトでも MVP アーキテクチャを卒業して MVVM にするか〜となった。

MVVM にするにあたり、いくつかのルールを制定したのだが、都度これに即したクラス群 (ViewModel. ViewModelTest など…) を作るのが面倒だったので、Android Studio による template のグループ機能を利用して自動生成するようにした。デフォルトでも Activity や Fragmemt をはじめとする様々なテンプレートが用意されている。

テンプレートから作成する様子は、ぽちぽちでやるとこんな感じ。

テンプレートを作成する

特にこう書くと良いという公式のドキュメントはなかった (あったら知りたいです)。そのため、Android Studio にもともとあるテンプレートの構成をめちゃくちゃ見た。

https://cs.android.com/android/platform/superproject/+/master:tools/base/templates/

見てみると、大体こんな構成になっているのがわかる。

ftl の拡張子は FreeMaker Template Language。ViewModel と ViewModelTest を生成するサンプルをぴゃっと作ったのでそれを用いる。

template.xml

Android Studio のメニューからFiles -> New -> なにかテンプレートを選択 の際に表示されるウインドウを構成したり、設定した変数を読み込みそれらを実行するためのファイルを指定する、基幹となるファイル。

これらの項目たちは parameter タグを用いて構成する。 Source Language と Target Source Set はデフォルトで表示されるようだ。parameter タグ内で id で指定した文字列が変数名になり、入力した文字列は $idで指定した名前 で参照できる。詳細は以下の template.xml。

globals.xml.ftl

任意の Key-Value の組を設定できる。例えばテンプレートをもとにして複数のファイルを同じディレクトリに生成する場合、出力先のディレクトリを変数にしておくと、それを参照すれば良いので便利。

template.xml 内で、globals タグを用いて指定して読み込む。

recipe.xml.ftl

テンプレートファイルを読み込み、実際にファイルを出力する役割がある。

多分主に使うのは以下。

<instantiate from="root/src/xxx.ftl" to="/path/to/yyy />

テンプレートのディレクトリにある root/src/xxx.ftl をもとに、/path/to/file へファイルを出力する。

<open file="/path/to/file />

指定したファイルをエディタで開く。

<#if id名> 処理 </#if>

boolean で指定し parameter タグ要素に対し、true であれば処理を行う。今回は ViewModel の ViewModelTest を生成していて、ViewModelFactory が必要なら生成してねとやっている。他にもそれを用いる画面はすでに存在している場合もあるかと思うので、Activity/Fragment も一緒に生成しますか? で用いると有用だと思われる。

これも template.xml 内で、execute タグを用いて読み込む。

慣例として globals.xml.ftl, recipe.xml.ftl と命名されている雰囲気があるが、ちゃんと template.xml 内でファイル名を指定すれば別名でも読み込まれる。

クラステンプレートファイル

慣例として、root 配下に置かれる ftl ファイル。これをもとにクラスが生成されるので好きなように書く。ftl ファイルなので同じように $idで指定した名前 で定義した値を参照できる。

ハマったところ

マルチモジュール対応

app/src/{main,test}/パッケージ名 だけならいいんだけど、マルチモジュール構成なので、app の部分を可変にする必要があった。それっぽいのを見つけられなかったので、生成時にウインドウで入力させて文字列を組み立てることで解決した。$srcDir という変数がデフォルトで用意されているものの、これは現状 Android Studio の Project タブでフォーカスがあたっているモジュールをさすっぽい。

入力されたパッケージ名 (com.mataku.app.ui.hoge) をディレクトリ構成に合わせる (com/mataku/app/ui/hoge) のがめんどそうと思ってたけど、パッケージ名渡したら変換してくれるslashedPackageName メソッドが用意されていた。

https://cs.android.com/android/platform/superproject/+/master:tools/adt/idea/android/src/com/android/tools/idea/templates/FmSlashedPackageNameMethod.java

https://cs.android.com/android/platform/superproject/+/master:tools/adt/idea/android/src/com/android/tools/idea/templates/FreemarkerUtils.java;l=46

デバッグ方法

macOS でいうと、/Applications/Android Studio の app ディレクトリ/Contents/plugins/android/lib/templates/任意のディレクトリ/ にテンプレートをディレクトリごと置いて、Android Studio を再起動すると読み込まれる。

テンプレートを変更した場合は Android Studio を読み直す必要があるのと、なにかエラーがあると生成されずに静かに終了するのでデバッグが面倒だった。

Android Studio 4.1 では使えない

手元の Android Studio はばしばしアップデートするのが功を奏したのか、Android Studio 4.1 では template 周りの API が変わっているらしく動こないというのを発見した。

Google の中の人によるサンプルも見つけたけど、公式でアナウンスが出たらマイグレーションすることにした。

Club kids never die

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store