月別: 2017年3月

Save Actionsというプラグインに感動した話

この記事は最終更新から3ヶ月以上が経過しています。情報が古い可能性があります。

DroidKaigi2017の会場には行かなかったけれども、参加した人や公開されたスライドなんかは一通りチェックしている。そんな中でこちらのスライドでSave Actionsなるプラグインを知る。

少し幸せになる技術

Android Studioで保存時にフォーマットを自動で揃える

Save Actions – JetBrains Plugin Repository

Save Actions – GitHub

Android Studioでビルドしたりファイルの保存が行われた際に、自動的にoptimize importやreformat codeを実行してくれるプラグインである。

ファイルの保存時にrefomart codeを実行する方法として、cmd+sにマクロを割り当てて行うという方法は以前から知っていたのだが、私は導入していなかった。というのも、私はAndroid Studioを使っていてただの一度も自分からファイルの保存を行ったことがないからである。そもそもcmd+Sを押す習慣がなかったのだ。それだったら気がついたときにalt+cmd+lでreformat codeを実行するのと大差ないなと思って導入しなかった。なのでreformat codeを実行することもよく忘れていた。(droidkaigi2017のリポジトリにフォーマットしてないコードをプッシュしたりしていた、申し訳なかった)

しかしこのSave Actionsプラグインに出会えたことで、今後そんなミスは起こさないだろう。

このSave Actionsは、Android StudioのPreference > Pluginsからは検索することができない。作者の方がAndroid Studioによる動作確認が取れていないのがその理由らしい。

導入するにあたっては、JetBrainsのPlugin Repositoryからzipファイルをダウンロードしてきて直接インストールする必要がある。

ちなみに、今のところAndroid Studioだからきちんと動作をしないという事象には出くわしていない。

素晴らしいなと感じたのが、ファイルが自動保存されるタイミングやビルド(デバッグ実行)したタイミングで、自動的にreformat codeが走ってくれること。しかもそのSave Actionsのreformat codeで修正された部分は、自分が修正したコードとは異なる色で表示される(新規が緑、変更が青、Save Actionsによるreformat分はグレーみたいな感じで色分けされる)。あくまでAndroid Studioのエディタ上での表示の話なので、コミットする際に別れてくれるわけではないけれども。

なお、Save Actionsを導入する場合は、必ずFile path exclusionsに.gradleファイルを追加する必要がある。

https://github.com/dubreuia/intellij-plugin-save-actions/issues/51

Gradleファイルをいじる際に、キーをタイプするたびにreformat codeなどが走るというバグがあるからだ。

個人的にはプラグインのバグというより、IntelliJ系IDEの仕様なのではないのかと思っている。gradleファイルはspaceを追加するだけでも「syncしろ」と言ってくるので、このあたりの動きが関連しているようにも思う。ともあれ、当座のところはgradleファイルをSave Actionsの対象外にすることでしのげる。

ともあれ、個人的にとても便利なプラグインだと思う。あまりに感動して作者にお礼のツイートを送ってしまうほど、ドンピシャなプラグインだった。

少し幸せになる技術というスライドで紹介されていたが、私は少しどころではなくかなり幸せになれた。ありがたい。

setLayoutParamsには親のViewGroupに属するLayoutParamsをセットする

基本的に私はViewをJavaのコードで生成することは稀なので、適当にやっていたのだけれど。

RelativeLayout parent = new RelativeLayout(context);
TextView hope = new TextView(context);
parent.addView(hoge);

みたいな感じでコードから生成したとき、このViewのwidth/heightにmatch_parentとかwrap_contentを設定するのに、LayoutParamsを使うことになると思う。

parent.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.MATCH_PARENT, RelativeLayout.WRAP_CONTENT));
hoge.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.MATCH_PARENT, RelativeLayout.WRAP_CONTENT));

みたいに。そこでLayoutParamsを指定するのに、なぜいちいちRelativeLayoutとかクラスを指定しているのだろうと、毎度のこと不思議に思っていた。別にViewGroupでもいいんじゃないのかとか思いながら、基本的にはAndroid Studioの補完によって出てきたものをそのまま使っていた。

とりあえずViewGroup指定しとけばオッケーだと思っていたのだが、どうもそれはオッケーではなかったらしい。たまたま今まで問題に出くわしていなかっただけだった。

親のViewGroupのLayoutParamsを使わなければならない

まあ大抵の場合、ViewGroupを使っておけば問題ないのだろう。LinearLayoutとかRelativeLayoutとかFrameLayoutとかにコードから生成したViewを追加していくだろうから。しかしバージョンによってはそれではうまく動かないことがあるらしいということがわかった。

私が出くわしたのは、ListViewに表示するViewをコードから生成したときに、ViewGroup.LayoutParamsを使うとクラッシュするという症状だった。ちなみにAndroid7で確認したら問題なく動いていたので、普通にスルーしていた。4.4で確認したらクラッシュした。

ListViewもViewGroupを継承しているのだからViewGroupでも問題ない気がするのに・・・。

ちなみにこれはAbsListView.LayoutParamsを使うことで、4.4でも7でもクラッシュしなくなくなった。

この問題から学んだことは、LayoutParamsは親のViewGroupに属するLayoutParamsを使わないといけないのだということである。LayoutParamsいっぱいあって適当に選んでいたが、今後はちゃんと指針が持てたという意味で、よい経験ができた。