こんにちはこんばんわイッシーです。すっかりブログの更新をサボってしましました。( ✖ Δ ✖)。。。そろそろ書いておかないとアレがアレなので書いておきます。

今回のネタは今更にはなりますがAsyncTaskについてです。通信や巨大ファイルの操作などをする時にメインスレッドで行っている方はいませんよね?(いたらすぐにやめてくださいね)

時間がかかる処理は別スレッドで行いUIスレッドでは行わないのは鉄則です。androidではメインスレッドが5秒以上応答しないと“Application Not Responding”(通称:ANR)が表示されて強制終了のダイアログが表示されます。従って、通信をメインスレッドで行ってはいけません。

さて、以下のようなコードを考えましょう。

public class Main extends ListActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(isConencted(this)){
            Task task = new Task();
            task.execute(URL);
        }
    }
   
    /**
     * isConencted
     * ネットワークの有無を確認する
     * @param context
     * @return boolean
     */

    protected boolean isConencted(Context context)
    {
        ConnectivityManager connectivityManger = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connectivityManger.getActiveNetworkInfo();
        if(networkInfo == null){
            return false;
        }
        return (networkInfo.isConnected());
    }
   
    /**
     * Task
     * バックグラウンド処理用のクラス
     */

    protected class Task extends AsyncTask<String, String, String>
    {
        @Override
        protected String doInBackground(String... params)
        {
            HttpClient client = new DefaultHttpClient();
            HttpGet get = new HttpGet(params[0]);
            byte[] result = null;
            String str = "";
            try{
                HttpResponse response = client.execute(get);
                StatusLine statusLine = response.getStatusLine();
                if(statusLine.getStatusCode() == HttpURLConnection.HTTP_OK){
                    result = EntityUtils.toByteArray(response.getEntity());
                    str = new String(result, "UTF-8");
                }
            }
            catch (Exception e) {
            }
            return str;
        }
       
        /**
         * onPostExecute
         * @param String result 通信結果
         * 結果を受け取ったときに・・・メインスレッド
         */

        @Override
        protected void onPostExecute(String result)
        {
            try {
                JSONObject json = new JSONObject(result);
            }
            catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }
}

■ポイント

ポイント1

isConenctedで圏外をチェックしてから通信(バックグラウンドタスクを実行)します。電波が無いところで通信しようとするのは無駄というものです。まあ、当然ですね。

ポイント2

別スレッドで実行されるのはdoInBackgroundだけであって、onPostExecuteはメインスレッドで実行されます。時間がかかる処理をonPostExecuteに書かないようにしましょう。

ポイント3

onPostExecuteが実行されたからといって、必ずしも通信が完了したとは考えないほうが良いと思います。地下鉄などではすぐに電波の状態が悪くなります。通信中に圏外になった場合、文字列が途中まで返ってくるのですがJSONでしたら当然パースできません。JSONExceptionできっちり処理してあげてください。

ポイント4

サンプルコードには書いてませんが同時に多数のAsyncTaskを実行するとメモリ不足で落ちる場合、synchronized(activity)して1本しか走らせないようにしましょう。

手短ですが本日はここまで。次回もandroidネタにしようかと思います。

Post Navigation