Webの人がAndroidアプリを作ってみて大事だな、と思ったことのまとめ
ちょっと前までの自分は、プライベートでRails, 仕事でPHPというWeb屋でしたが、最近になってプライベートも仕事もAndroidをいじるようになりました。
そこで感じたWebとの違い、今後のアプリ開発で押さえておきたいポイントを軽くまとめてみます。題して「Androidのココは気をつけろ!」
ListView をナメてかかるな!
Webアプリを作っていると必ずは出てくる同じ項目をリストで表示する機能。大抵のHTMLレンダリングエンジンでfor文みたいなので回して出力するだけです。
ここでWeb屋はリストビューを甘く見て、早く実装できる。と勘違いします。これに注意。
Android の場合、1行のレイアウトのファイルを作り、それをメモリに入れて使いまわすという方法を取ります(取り組めばわかると思いますがconvertView辺り)。 単純なリストビューなら確かにすぐ終わりますが、チェックボックスや一部の領域でタップ可能なリストなど、ちょっと凝った機能になるだけでこのレイアウトの使いまわしおよびイベントの管理がとても難しくなります。 私の場合、行をタップしてその行の中にあるチェックボックスにチェックを入れる、という一見とても簡単そうな機能を実装するのに丸2日ドハマりしました。。
画像を表示するだけでめちゃめちゃ重くなって落ちる、ということもよくあります。
具体的にこう解決しろ、とはここでは言いません。
ただリストビューの工数見積もりには気をつけろ、ということを伝えたいです。
画像を作ってもらう人にはこれは伝えておけ!
けっこう画像を作ってもらう人もAndroidアプリ用の画像は初めて、という人は多いです。
そんな人に伝えなきゃならないと思っているのは以下のようなものです。
- 画像はhdpi, mdpi, ldip, xdpi などサイズ毎の画像が必要である
- 画像の文字を埋め込まない!(国際化対応ができなくなる)
- サイズごとの画像名は必ず同じにする
- 画像命名規約を守る
- ボタンとかはできるだけ自分たちで作る
命名規約として、最初は小文字、それ以降はアンダーバー、小文字、大文字、数字のいずれかのみが許されています。これを守ってくれないと、それぞれのサイズごとの画像をリネームしなきゃいけない作業が待ってるので、予め伝えておきましょう。
ボタンとかはstyleを用いてグラデーションとか角丸とかXMLで作れます。そういうのは自分で頑張って作った方がリソースの節約になります。
サクサク動くアプリの実現の為に、バックグラウンドの使い方を習得しよう
Web方面から来た人は意外と「スレッド」とか使ったことすらない、という人は多いのではないでしょうか?私もあまり使った経験がなかったです。androidアプリを使い始めて本格的にスレッドを使いはじめたのですが、意外と普通に使えました。
Androidでのバックグラウンドの実行は思いつく限りでは4つくらいあります。
・AsyncTaskを利用する
・Threadを作ってからのHandler
・Serviceを起動
・BroadcastReceiver
Web屋がAndroidを作るという場合は、たいていはWebのアプリと連携したAndroidアプリを作ると思うので、そのケースに対して有効なバックグラウンドの使い方は前者2つだと思います。
色々なAndroidのサンプルではAsyncTaskが用いられることが多いです。が、個人的にはあまり好きじゃないです。理由としてはオーバーライドしなきゃいけないメソッドの引数や戻り値が他のメソッドの戻り値などが読みにくいのと、preとpostのメソッドも特に用がなくても作る必要があるためです。まぁ好みの問題です。
個人的にはThreadを作ってからのHandlerをお勧めしたいです。
軽く説明します。
けっこう見た感じ、汚いソースになりそうですね。。そういうのを解決してくれるのがAsyncTaskなのかも。私はコメント部分は必ず一つのメソッドを実行するにとどめています。
Handler handler = new Handler();
Thread t = new Thread(new Runnable() {
@Override
public void run() {// 重い処理をここに書く
handler.post(new Runnable() {
@Override
public void run() {// バックグラウンド処理完了後で、
// UIを更新したい場合ここに書く}
});
}
});
t.start();
このHandlerが最初ちょっとわかりにくかったので、自分の理解を説明します。
Androidには"UIスレッド"というのがメインのスレッドになってます。 UI更新の処理のまとまり(Runnableオブジェクト)は、それぞれスタックに積まれていて、Looperが一個一個実行してくれます。 handler.post で、そのUI更新のスタックに指定の処理を積み上げてくれます。これによりバックグラウンドスレッドで完了した後にUI更新が可能になるそうです。(図がないからわかりにくさMAXですな・・)
重い処理をどうにかしたい場合はAsyncTaskのほかにこの方法も検討してみてください。
"コールバック"を使おう
これはAndroidアプリ作るうえで便利なテクニックだなと思ってます。これを使うとソースがダイブ綺麗になるのではないでしょうか。
具体的にはインタフェースを使います。てかインタフェース便利すぎw
基本構造はこれ!何かの処理を他のクラスに任せて、それが終わった後の処理が書きたいなーって時にぜひ使ってみてください。
public interface Callback {
public void onFinished();
}public class Hoge implements Callback {
public void doSomething() {
Fuga.doInBackground(this);
}@Override
publc void onFinished() {
//処理完了後の処理
}
}public class Fuga {
public static void doInBackground(Callback callback) {
//バックグラウンドで何かするcallback.onFinished();
}
}
LinearLayout と RelativeLayoutをうまく使い分けよう
Android難しい、と思われるところでレイアウトを構成するのが難しいという意見があります。確かに私も最初は全然思う通りのレイアウトを作れませんでした。そして環境依存でまた色々修正しないといけなかったり・・。レイアウトはAndroidアプリ開発するときには必ず苦戦すると思います。
よく一番最初に読む本ではLinearLayoutがよく紹介されると思います。これがよくないと思ってるんですよねー・・。私はRelativeLayoutの方をよく使います。
RelativeLayoutは画面内の一番下とか上とかのレイアウトを指定して、それを元に他のレイアウトはその基準に比べてどの位置にいるかをセットします。
これの良い所は、画面サイズに応じて特定の部分の拡大縮小も結構カンタンにやってくれるところです。この文字はどんな端末でも絶対出して、ここはちっちゃな端末の場合はスクロールしたりで対応しようみたいなことができます。
確かにLinearLayoutでも同様のことがLayoutWeightを使えばできます。でもこれにはとても大きな問題があって、TextViewをLayoutWeightで調整すると、一部の端末で文字が途切れたりするような現象が発生します。端末依存が出やすいです。。前はLinearLayoutのLayoutWeightで頑張ってたんですが、この問題が発覚しだしてからRelativeLayoutを積極的に使うようにしています。
LinearLayoutは、何かの要素を均等に配置したい、って場合に使ってます。
FrameLayoutってのもたまに使います。何かを重ねて表示したいといった場合くらいかな。
色々あるけど、Androidアプリ開発楽しいです!Webアプリ作ってる方も是非始めてみましょう〜。