アプリケーションの開発を進めていくうちに、動作が遅くなってしまうことはよくある。しかし、多くの場合、何が遅くなった原因なのかはっきりしない。今回遅くなったのは、初期画面の表示。行っているのは、SurfaceView の Canvas に線を引いて、日付と画像を貼り付けているだけ。一部、グラデーションなども行っているが、たいした処理ではない。線を引いただけの時は一瞬で動作したのに、日付や画像を描画したら、1秒弱かかってしまうようになった。遅くなった原因を推測すると・・・
- アンチエイリアスをかけている
- 描画する際に独自のクラスを何回も new している
- 描画位置の計算が遅い
などだ(ずいぶん悪いことばかりしてるなんて言わないでください)。それぞれ、
long l = System.currentTimeMillis(); ... System.err.println((System.currentTimeMillis() - l));
ではさんで時間を計測してみた。どうも数字を描画している箇所が遅い。アンチエイリアスを外してみたが、時間はかわらなかった。数字を描画する箇所の1つずつの処理の時間を計測してみると、SimpleDateForamt を new している箇所が遅い。
たしかに、String.format() 系のメソッドはコストが高い。Android には、android.text.format.DateFormat が用意されているので、Java 標準の SimpleDateFormat、Android の DateFormat、単純に Calendar から日付を取得する3つの方法を比較してみた。
標準の SimpleDateFormat を使う
エミュレーター上で、約9msかかる。
new SimpleDateFormat("d",Locale.JAPAN).format(date);
android.text.format.DateFormat を使う
エミュレーター上で、約5msかかる。
CharSequence s = DateFormat.format("d", System.currentTimeMillis()); s.toString();
Calendar から取得
エミュレーター上で、約2msかかる。
Calendar c = Calendar.getInstance(); c.setTimeInMillis(System.currentTimeMillis()); c.get(Calendar.DAY_OF_MONTH);
日付をフォーマットする処理は、約100回行っている。一回の処理が1/5になれば体感速度は相当上がるはず。今回は複雑なフォーマットは不要なので、Calendar から取得した値を使って表示するように変更してみることにした。