Androidの通信周りの
コーディングについて
私です
名前 : 高木翔一
会社 : 株式会社ディディアイディ
Twitter : @fly1ncu
blog : http://blog.fly1ncu.com
スライドはアップロードするのであとでゆっくりみてね
Activityに2000行も3000
行も書かないでほしい(切実)
通信周りがすっきりしない4つの理由
•  JSONやXMLのパースめんどい
•  マルチスレッドプログラミングめんどい
•  クラス分割うまくいかない
•  エラー処理めんどい
JSONやXMLのパース
JSONやXMLのパース
{
“id” : 0,
“name” : “tsubu”,
“place_name” : “a-team”
}	
public class Meeting {
private int id;
private String name;
private String placeName;
public void setId(int id) {
this.id = id;
}
public void getId() {
return id;
}
// (省略)
} 	
JSON
POJO
パース(デシリアイズ)
シリアライズ
パーサーを書く
public class MeetingParser {
private interface Key {
String ID = “id”,
String NAME = “name”,
String PLACE_NAME = “place_name”
}
public static Meeting parse(String json) {
Meeting meeting = new Meeting();
JsonObject jsonObject = new JsonObject(json);
meeting.setId(jsonObject.getInt(Key.ID));
meeging.setName(jsonObject.getString(Key.Name));
meeting.setPlaceName(jsonObject.getString(Key.PLACE_NAME));
return meeting;
}	
Androidには標準でJsonObjectクラスが準備されている
要素が増えてくるとめんどくさい (´Д`)
パーサーを書かない
オープンソースライブラリをつかうとパーサー書かなくてもいい
• JsonPullParser
• GSON
JsonPullParserを使う
@JsonModel
public class Meeting {
@JsonKey private int id;
@JsonKey private String name;
@JsonKey private String placeName;
public void setId(int id) {
this.id = id;
}
public void getId() {
return id;
}
// (省略)
} 	
POJO
private void parse(String json) {
Meeting meeting = MeetingGen.get(json);
}	
POJOにマーカーアノテーションをつけるだけ!
XMLはSimpleがいいよ!
@Root
public class Meeting {
@Element private int id;
@Element private String name;
@Element private String placeName;
public void setId(int id) {
this.id = id;
}
public void getId() {
return id;
}
// (省略)
} 	
POJO
マルチスレッドプログラミングの必要性
マルチスレッドプログラミングの必要性
•  AndroidはUIスレッドで通信できない
–  昔はできたのよ。やらないけど
•  別スレッドで通信しなきゃ
•  UIスレッド以外ではUIを変更できない
•  UIスレッドで終了時のUI変更しなきゃ
通信部分のバックグラウンド処理
private Handler mHandler = new Handler();
private void downloadString(final String url) {
mHandler.post(new Runnable {
@Override
public void run() {
HttpClient client = new DefaultHttpClient ();
HttpGet httpGet = new HttpGet(url);
HttpResponse httpResponse = client.execute(httpGet);
String response;
response = EntityUtils.toString(response.getEntity(), "UTF-8");
// 文字列をパースするとか
Meeting meeting = MeetingGen.get(response);
onDownloaded(meeting);
}
}
}	
ネスト多くねー?(#^ω^)
UIスレッドの処理
private void onDownloaded(final Meeting meeting) {
// Activity#runOnUiThread
runOnUiThread(new Runnable {
@Override
public void run() {
mProgresDialog.dismiss(); // プログレスダイアログを消す
setMeeting(meeting);
}
}
}	
ネスト多くねー?(#^ω^)
AndroidAnnotationsを使う
@Background
void downloadString(final String url) {
HttpClient client = new DefaultHttpClient ();
HttpGet httpGet = new HttpGet(url);
HttpResponse httpResponse = client.execute(httpGet);
String response;
response = EntityUtils.toString(response.getEntity(), "UTF-8");
// 文字列をパースするとか
final Meeting meeting = MeetingGen.get(response);
onDownloaded(meeting);
}	
@UiThread
void onDownloaded(final Meeting meeting) {
mProgresDialog.dismiss(); // プログレスダイアログを消す
setMeeting(meeting);
}
AsyncTaskを使う
private class DownloadTask extends AsyncTask<String, Integer, Meeting> {
ProgressDialog progressDialog;
@Override
protected void onPreExecute() {
progressDialog = new ProgressDialog(SampleActivity.this);
progressDialog.show();
}
@Override
protected String doInBackground(String... params) {
HttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
HttpResponse httpResponse = client.execute(httpGet);
String response;
response = EntityUtils.toString(response.getEntity(), "UTF-8");
return MeetingGen.get(response);
}
@Override
protected void onPostExecute(Meeting meeting) {
progressDialog.dismiss();
setMeeting(meeting);
}
AndroidAsynchrousHttpを使う
// UIスレッドでコールする
AsyncHttpClient client = new AsyncHttpClient();
client.get(“http://hoge.jp”, new AsyncHttpResponseHandler {
@Override
public void onSuccess(String response) {
// このなかはUIスレッド
progressDialog.dismiss();
}
});
クラス分割したときのクラス間の処理
クラス分割したときのクラス間の処理
通信部分を別クラスにすると通信終了時に
元のクラスになんか合図したいよね
強結合での実装
public class DownloadTask{
public void execute(MainActivity mainActivity) {
// (略) 通信の処理とか
mainActivity.onDownloaded();
}
} 	
元のクラスを引数にして、メソッドをコールする
コールバックでの実装
public class DownloadTask{
public interface CallBack {
void onDownloaded();
}
public void execute(CallBack callBack) {
// (略) 通信の処理とか
if (null != callback) {
callback.onDownloaded();
}
}
}
コールバックでの実装
public class MainActivity extends Activity
impletents DownloadTask.Callback {
private void startDownload() {
new DownloadTask().execute(this);
}
@Override
public void onDownloaded() {
// (略) ダウンロード後の処理とか
}
}	
public class MainActivity extends Activity {
private void startDownload() {
new DownloadTask().execute(new DownloadTask.Callback {
@Override
public void onDownloaded() {
// (略) ダウンロード後の処理とか
}
});
}
}
AsyncTaskLoaderでの実装
public class SampleActivity extends Activity implements
LoaderCallbacks<Meeting> {
// 省略	
@Override
public Loader<Meeting> onCreateLoader(int id, Bundle args) {
// 開始処理を書く
MeetingLoader loader = new MeetingLoader(this);	
loader.forceLoad();
return loader;
}
@Override
public void onLoadFinished(Loader<Meeting> loader, Meeting meeting) {
// Loaderが終了すると呼ばれる	
}
@Override
public void onLoaderReset(Loader<Meeting> meeting) {
// Loaderがリセットされた時によびだされる	
}
}
AsyncTaskLoaderでの実装
public class MeetingLoader extends
AsyncTaskLoader<Meeting> {
//省略
@Override
public List<Meeting> loadInBackground() {
Meeting meeting;
// ダウンロード処理など
return meeting;
}
}
エラー処理はガンバル&めんどくさがらない
try {
downloadTask();
} catch (Exception e) {}	
やめてください
エラー処理
public class DownloadTask{
public interface CallBack {
void onDownloaded();
void onDownloadFailured();
}
public void execute(CallBack callBack) {
try {
// (略) 通信の処理とか
if (null != callback) {
callback.onDownloaded();
}
} catch (Exception e) {
if (null != callback) (
callback.onDownloadFailured();
}
}
}
}
ご清聴ありがとうございました

Androidの通信周りのコーディングについて