通信をワーカースレッドで行うように改良してみました。しかし、AndroidはActivityの状態遷移で場合によっては強制終了させられることもあるらしいので、onPauseの処理で確実にワーカースレッドを止めて破棄するにはどうすればよいのか思案中、、、終わるのをいくらでも待っていられるならjoinすればいいだけでしょうが、そういうもんでもなさそうだし。
通信の別thread化にともない、結果が非同期で返却されるので前回のonCreateのListener部分を変更しました。
// 品番検索ボタンListenerの設定 Button btn = (Button) this.findViewById(R.id.btnSearch); btn.setOnClickListener(new OnClickListener(){ @Override public void onClick(View view) { try { // 入力した品番を取得 EditText edit1 = (EditText) findViewById(R.id.txtHinban); String hinban = ((SpannableStringBuilder) edit1.getText()).toString().trim(); if (hinban.length() == 0) throw new Exception("品番を入力してください。"); prog = ProgressDialog.show(MainActivity.this, "通信中", "HTTPリクエスト送信中"); // HTTP通信処理で品番を検索 actionSearch(hinban); } catch (Exception ex) { new AlertDialog.Builder(MainActivity.this) .setTitle("Error") .setIcon(android.R.drawable.ic_dialog_alert) .setMessage(ex.getLocalizedMessage()) .show(); } } });
HTTPの通信部分を別threadに実行させ、結果をハンドラにMessageとして渡すようにしました。
private void doPost(String action, List<NameValuePair> post_params, final int what) { try { // Http通信パラメーター生成 SchemeRegistry schreg = this.getSchem(); HttpParams params = this.getHttpParams(); // HttpClientの構築 ThreadSafeClientConnManager connManager = new ThreadSafeClientConnManager(params, schreg); final DefaultHttpClient client = new DefaultHttpClient(connManager, params); for (Cookie cookie : this.mSavedCookies) { client.getCookieStore().addCookie(cookie); } // POST要求生成 final HttpPost request = new HttpPost(appurl + action); request.setEntity(new UrlEncodedFormEntity(post_params, encode)); request.setHeader("Connection", "Keep-Alive"); // Responseハンドラ生成 final ResponseHandler<String> response = new ResponseHandler<String>() { @Override public String handleResponse(HttpResponse response) throws ClientProtocolException, IOException { // 実行結果の確認 switch (response.getStatusLine().getStatusCode()) { case HttpStatus.SC_OK: // Response内容を取得して表示 String msg = EntityUtils.toString(response.getEntity(), encode); return msg; case HttpStatus.SC_NOT_FOUND: throw new RuntimeException("Error: Not Found"); default: throw new RuntimeException("Error: something"); } } }; // POST実行 new Thread () { private Message msg = hdlResult.obtainMessage(); @Override public void run() { // Message準備 msg.what = what; Bundle bundle = new Bundle(); try { // 要求実行と返信受信 String result = client.execute(request, response); // Cookie保存 saveCookie(client); // 要求結果処理 List<String> json = parseJson(result); bundle.putStringArray("RESPONSE", json.toArray(new String[0])); this.sendMessage(bundle); } catch (Throwable e) { msg.what = -1; if (e instanceof SocketTimeoutException) bundle.putString("Error", "通信エラー発生:\nタイムアウトが発生しました。"); else bundle.putString("Error", "通信エラー発生:\n" + e.getMessage()); this.sendMessage(bundle); } finally { client.getConnectionManager().shutdown(); this.msg = null; } } private void sendMessage(Bundle bundle) { msg.setData(bundle); hdlResult.sendMessage(msg); } }.start(); } catch (Throwable e) { throw new RuntimeException(e); } }
結果処理用のハンドラです。Activityのメンバ変数として生成しています。結果を受け取りUIの操作を行い表示を行います。
private final Handler hdlResult = new Handler() { public void handleMessage(Message msg) { String result[] = null; try { prog.dismiss(); // 進捗ダイアログ画面を終了 switch (msg.what) { case -1: // 通信中に例外が発生した場合 new AlertDialog.Builder(MainActivity.this) .setTitle("Error") .setIcon(android.R.drawable.ic_dialog_alert) .setMessage(msg.getData().getString("Error")) .show(); break; case 0: // 検索問い合わせ結果 result = msg.getData().getStringArray("RESPONSE"); TextView edit2 = (TextView) findViewById(R.id.txtResult); if (result[1].equals(MSG_SEARCH_SUCCESS)) { // 取得した品番情報を表示 edit2.setText(result[2]); } else { edit2.setText("該当なし"); } break; } } catch (Exception e) { Log.d("ERROR", e.getLocalizedMessage()); } } };
private void actionSearch(String hinban) throws Exception { List<NameValuePair> params = new ArrayList<NameValuePair>(); params.add(new BasicNameValuePair("hinban",hinban)); this.doPost("search.action", params, 0); }
一応、動いてはいますが、どうなんでしょう、、、
次回こそはサーバ側の紹介をしていこうかと思います。