Twitter4Jを用いたツイッタークライアントの開発テストにて、非同期処理をテスト実装したときのノートです。
AsyncTaskは、「AsyncTaskを継承したclassを定義」して使います。以下の例は、非同期処理を行っている最中の「進捗」を表示する処理も入れています。わかりづらいかもしれませんが、よーく見てください。
private class DownloadTask extends AsyncTask<*1, *2, *3>{
@Override
protected *3 doInBackground(*1... arg_name){
publishProgress(value);
}
@Override
protected void onProgressUpdate(*2... arg_name){
}
@Override
protected void onPostExecute(*3){
}
}
非同期処理というのは、表で動いているActivityとは別のところで処理することをいいます。なぜそれが必要なのか?それは、Activityで時間のかかる処理、例えばネットワークダウンロードとかを処理していると、Activityが止まってしまうんですね。厳密にはリスナーをセットしたボタンとかは動くかもしれませんが(未確認)。
ユーザーの立場からすれば、アプリが「ロック」してみえる状態ってイライラしますよね?そして、10秒くらい処理に時間がかかるとAndroidのシステムが割り込みをかけて処理を止めてしまいます。これでは困るわけで。だから非同期処理を行うのです。
doInBackground(args)、というメソッドがバックグラウンド処理を行う本体になります。argsの型は、上記コードの1行目にある*1で規定します。この中で、「publishProgress(value)」を呼び出すと、onProgressUpdateにvalueが渡されるので、この値を用いてProgressを更新します(Progressは進捗という意味)。
doInBackground()の実行が完了すると、onPostExecuteが呼ばれます。doInBackground()の返値の型は、*3で規定します。
ぼくが作成中のTwitterクライアントのコードを公開します。このコードをコピペしただけでは動きませんけどね(笑)
一応補足しておくと、
引数の型
第一引数は使っていない(doInBackgroundで使わない)のでVoid(voidではないんです)
第二引数は、進捗状況を数値で渡すのでInteger
第三引数は、タイムラインデータをclassのリスト型で処理するので、List<bindData>(bindDataは独自定義class)
/////////////////////////////////////////////////////////////
/// AsyncTask
/////////////////////////////////////////////////////////////
private class DownloadTimeLine extends AsyncTask<Void, Integer, List<bindData>> {
@Override
protected List<bindData> doInBackground(Void... params) {
/// 初期化
List<bindData> data = new ArrayList<bindData>();
adapter = new TweetAdapter(con, R.layout.timeline_item, data);
ResponseList<twitter4j.Status> homeTl;
try {
homeTl = tw.getHomeTimeline();
int tl_cnt = homeTl.size();
int cnt = 0;
for(twitter4j.Status status : homeTl){
String user_name = ((twitter4j.Status) status).getUser().getName() +
"/@" + ((twitter4j.Status) status).getUser().getScreenName();
//String tweet_time = status.getCreatedAt().toString();
int year = ((twitter4j.Status) status).getCreatedAt().getYear()+1900;
int month = ((twitter4j.Status) status).getCreatedAt().getMonth()+1;
int day = ((twitter4j.Status) status).getCreatedAt().getDate();
int hour = ((twitter4j.Status) status).getCreatedAt().getHours();
int min = ((twitter4j.Status) status).getCreatedAt().getMinutes();
String tweet_time = String.format("%d/%d/%d %02d:%02d", year, month, day, hour, min);
String tweet = ((twitter4j.Status) status).getText();
URL icon_url = ((twitter4j.Status) status).getUser().getProfileImageURL();
InputStream is;
try {
is = icon_url.openStream(); /// Exception
Bitmap bmp = BitmapFactory.decodeStream(is);
//setProgress(10000*(i++/tl_size));
data.add(new bindData(bmp, user_name, tweet_time, tweet));
cnt++;
publishProgress( (int) ((cnt/(float) tl_cnt) * 100));
} catch (IOException e) {
// TODO 自動生成された catch ブロック
Log.e("", "アイコンの読み込みに失敗しました。");
e.printStackTrace();
}
}
} catch (TwitterException e1) {
// TODO 自動生成された catch ブロック
e1.printStackTrace();
}
return data;
}
protected void onProgressUpdate(Integer... progress){
setProgressPercent(progress[0]);
}
protected void onPostExecute(List<bindData> data){
/*String data_size = String.format("%d", data.size());
showTimeLine("data size = " + data_size);*/
setListAdapter(adapter);
}
}