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

記すに足らず。

デザイン&プログラミングのことも書くし、それ以外のことも書く。

【Android】メインスレッド(要は画面処理)でhttpリクエスト投げようとしたら怒られた。 〜NetworkOnMainThreadException〜

Android

Androidアプリで、画面からなにか処理した時に
外部のWeb APIから情報を取得(http getリクエスト)するロジックを書いていたのですが、
なぜかリクエスト投げるとNetworkOnMainThreadExceptionというエラーが返ってくる。。


調べてみると、どうやらAndroid3.0以上では
メインスレッドからネットワーク処理を行うことを許していないらしい。
確かにエラーが出たときはAndroid4.?でデバッグしてました。


と、いうわけで
「AsyncTask」を使って別スレッドでhttpリクエストを投げることにしました。

〜大変参考になりました!〜
android開発|「AsyncTask」利用:android.os.NetworkOnMainThreadExceptionエラーへの対応方法 — 検索プログラマのメモ帳
AsyncTaskを使った非同期処理のきほん | Developers.IO
Activityから非同期(スレッド)処理へデータを渡す - 技術脳塗


Async Taskを使って別スレッド処理


簡単ですが実装例。

まず非同期処理を行うクラスを作りました。
AsyncTaskをextendしたクラスです。

public class AsyncHttpRequest extends AsyncTask<Uri.Builder, Void, String> {
    
    private Activity mainActivity;

    public AsyncHttpRequest(Activity activity) {

        // 呼び出し元のアクティビティ
        this.mainActivity = activity;
    }
    
    // このメソッドは必ずオーバーライドする必要があるよ
    // ここが非同期で処理される部分みたいたぶん。
    @Override
    protected String doInBackground(Uri.Builder... builder) {
        // httpリクエスト投げる処理を書く。
        // ちなみに私はHttpClientを使って書きましたー
    }


    // このメソッドは非同期処理の終わった後に呼び出されます
    @Override
    protected void onPostExecute(String result) {
        // 取得した結果をテキストビューに入れちゃったり
        TextView tv = (TextView) mainActivity.findViewById(R.id.name);
        tv.setText(result)
    }
}

そして呼び出す側。

// 例えばボタン押した時の処理ならonClickメソッドの中とか。

// httpリクエストを入れる変数
Uri.Builder builder = new Uri.Builder();

// …

AsyncHttpRequest task = new AsyncHttpRequest(this);
task.execute(builder);

// …

簡単に書くとこんな感じ。


AsyncTaskの型パラメーター3つの指定ですが、参考にしたサイトによると


1つ目:メインスレッドから非同期処理に渡す引数の型
呼び出すexecuteメソッドの引数&doInBackgroundメソッドの引数の型

2つめ:進捗度合を表示する時に利用したい型
onProgressUpdateメソッドの引数の方

3つ目:バックグラウンド処理完了時に受け取る型
doInBackgroundメソッドの戻り値&onPostExecuteメソッドの引数


となっているよう。

型パラメーター見てもわかる通り、
AsyncTaskという抽象クラスには他にも実装例には登場していない
オーバーライドできるメソッドがあります。
非同期処理の前に実行できる処理とか、進捗度合いを出力できるメソッドとか。
上記の参考リンクを参照したり検索したりしてみてください。


※ちなみにHttpClient使うときは、マニフェストファイルに

<uses-permission android:name="android.permission.INTERNET" />

追加しないと動かないんで要注意です。



Android、いろいろハマるわー(~_~)