【Android】HTTP通信での非同期処理の方法
Android 3.0以降、メインスレッドでネットワーク処理を行うとエラーにるみたいです。
メインスレッドにネットワーク処理を書いてしまうと、NetworkOnMainThreadException
というエラーがでてしまいます。
メインスレッドでHTTP通信を行う場合は、非同期処理をしないといけないみたいです。
そこで、
・AsyncTaskLoader
(非同期処理のロード)
・LoaderCallback
(非同期処理のコールバック)
を使用します。
AsyncTaskLoader
非同期処理(ロード)を行なうために以下ファイル(HttpAsyncTaskLoader.java
)を作成します。
public class HttpAsyncTaskLoader extends AsyncTaskLoader<String> { /** 引数 */ private String mArg; /** 非同期処理での結果を格納 */ private String mData; public HttpAsyncTaskLoader(Context context, String arg) { super(context); this.mArg = arg; } @Override public String loadInBackground() {// 非同期処理を記述 try { // 適当に時間がかかる処理 Thread.sleep(3000); mData = "hoge"; } catch (InterruptedException e) { e.printStackTrace(); } return mData; } @Override protected void onStartLoading() {// 非同期処理の開始前 // ActivityまたはFragment復帰時(バックキーで戻る、ホーム画面から戻る等)に再実行されるためここで非同期処理を行うかチェック if (mData != null) {// 結果がnullではないは場合は既に実行済みとして非同期処理は不要 // deliverResultで結果を送信 deliverResult(mData); } if (takeContentChanged() || mData == null) { // 非同期処理を開始 forceLoad(); } } @Override protected void onStopLoading() {// Loader停止時の処理 // 非同期処理のキャンセル cancelLoad(); } @Override public void deliverResult(String data) {// 登録してあるリスナー(LoaderCallbacksを実装したクラス)に結果を送信 if (isReset()) {// Loaderがリセット状態かどうか // trueの場合はLoaderがまだ一度も開始していない、resetメソッドが呼ばれている return; } mData = data; super.deliverResult(data); } @Override protected void onReset() { // reset呼び出し時、Loader破棄時の処理 super.onReset(); // Loaderを停止 onStopLoading(); // データをクリア mData = null; } }
LoaderCallbacks
以下のコードを追加で、非同期処理の結果を受け取ることができます。
public class QuestionsAndAnswersFragment extends Fragment implements LoaderManager.LoaderCallbacks<String> { . . . private static final int LOADER_ID = 0; @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // Loaderに渡す引数 Bundle args = new Bundle(); args.putString("hoge", "hoge"); // Loader初期化と開始 getLoaderManager().initLoader(LOADER_ID, args, this); } @Override public Loader<String> onCreateLoader(int id, Bundle args) {// 非同期処理を行うLoaderを生成 // getLoaderManager().initLoaderで一回のみ呼び出される String data = args.getString("hoge1"); return new HttpAsyncTaskLoader(getActivity(), data); } @Override public void onLoadFinished(Loader<String> loader, String data) {// 非同期処理完了時 // ここでView等にデータをセット // ログて返ってきた値を確認 Log.v("tag", data); // Loaderを停止・破棄(次回の読み込みでもう一度initLoaderをできるようにするため) getLoaderManager().destroyLoader(loader.getId());// loader.getId() == LOADER_ID(initLoaderの第一引数) } @Override public void onLoaderReset(Loader<String> loader) {// Loaderが破棄される時に呼び出し // Loaderが参照しているデータを削除する } . . . }
参考サイト: