読者です 読者をやめる 読者になる 読者になる

woshidan's loose leaf

ぼんやり勉強しています。

Keeping Your App Responsiveを読んだ

http://developer.android.com/intl/ja/training/articles/perf-anr.html

上記を読んだ雑なメモ。

  • システムはアプリケーションが一定以上の時間応答しないとANRダイアローグを出して、そのアプリケーションを閉じるかどうか尋ねて、ユーザーにアプリを閉じる選択肢を与える
  • システムがANRを出さないように設計すべき

ANRが起こる条件

  • UIスレッドでネットワーク通信やゲームの表示用オブジェクトの生成等をやるとx
  • 時間がかかりそうな処理はUIスレッドで行わない
    • ワーカースレッドを作ってそちらでほとんど行う
  • これによって、UIスレッド(ユーザーインターフェースイベントループ*1を動かしている)を稼動状態にして、システムを凍結させるのを防ぐ
  • このようなスレッド処理はクラス単位で行われる => 応答性はクラス単位の問題だと考えることが多い(普通はメソッド単位で考えるが)

  • Androidでは、アプリケーションの応答性はActivity ManagerとWindow Manager system servicesで監視されている。

  • AndroidがANRを表示する条件は下記の2つの条件を検出したとき
    • キータッチなどの入力イベントに対して5秒以内に反応がないとき
    • BroadcastReceiverの処理が10秒以内に終らなかった時

ANRを避ける方法

  • インプットイベントやインテントを受け取るチャンスをアプリにあげないようなコード(通常、何も指定しないとすべての処理をUIスレッドで行うが、そんなコード)
  • UIスレッドで動くメソッドは小さくしよう

    • 特にActivityのonCreate()onResume()といったライフサイクルメソッドで行うセットアップ処理は可能な限り小さくしよう
      • いまはバックグラウンドで用意するための処理を呼び出し、みたいな感じだっけか
    • 画像の整形やネットワーク/DBヘの接続はバックグラウンドで
  • もっと効率的に長時間のワーカースレッドを作る方法は AsyncTaskクラスの利用

    • AsyncTaskクラスを継承して、doInBackground()をオーバーライドする
    • 進捗の変化については、(doInBackground()内から)publishProgress()メソッドが使える
      • これは同じクラスに書いたonProgressUpdateメソッドを呼び出す
    • onProgressUpdateはUIスレッドで動く
    • 処理が終了した時は、同じクラスのonPostExecuteメソッドが呼ばれる
  • 作ったAsyncTaskのクラスのジョブの実行は下記のような感じ。
new DownloadFilesTask().execute(url1, url2, url3);
  • もっと複雑な場合は、自分自身のThreadクラスを作るか、HandlerThreadクラスを利用する。
  • そうする場合、あなたはスレッドの優先順位をProcess.setThreadPriority()メソッドでセットし、THREAD_PRIORITY_BACKGROUNDの値を指定する必要がある。
    • そうしないとUIスレッドより優先してバックグラウンド処理が行われ、別スレッドに書いたのにANRが起こるとかある。
  • ThreadやHandlerThreadクラスを実装するとき、それらの完了までUIスレッドをブロックしないようにする(=つまり、Thread.wait()Thread.sleep()は呼ばない)
  • メインスレッドをブロックするかわりにメインスレッドはそれらのスレッドの完了時のpost backを受け取るHanlderを提供する
  • メインスレッドでネットワークの処理等を書いてないかを調べるStrictモードがあるらしい

応答性を強化する

  • ユーザーがあれ?と思うのは0.1~0.2s
  • バックグラウンドジョブに時間がかかる場合ProgressBarなどで進捗を示す
  • 計算はワーカースレッドで
  • 初期化処理に時間がかかるならスプラッシュが面を入れてはどうでしょう
  • SystraceやTraceviewといったパフォーマンスツールを使ってみよう

感想

  • ANRの条件は知ってた
  • なんだか、AsyncTaskの書き方に親しみが出てきた
  • 余裕が出てきたら、SystraceやTraceviewといったパフォーマンスツールを使ってみたい
英語
sluggish 動きののろい

*1:ちょっと分かりきってない単語だ