【Android】メインスレッド(要は画面処理)でhttpリクエスト投げようとしたら怒られた。 〜NetworkOnMainThreadException〜
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、いろいろハマるわー(~_~)