참고 : http://developer.android.com/reference/android/os/AsyncTask.html
AsyncTask
안드로이드는 UI Thread 에서 일정 시간동안 유저의 반응에 응답하지 못하면 ANR(Application Not Responding) 오류를
발생시킨다. 하지만 네트워크를 통한 데이터 전송 등 계속적인 작업이 실행되어야 할 경우 AsyncTask를 상속받은
클래스를 통해서 작업을 수행하는 것으로 ANR 오류를 방지할 수 있다.
(1) 작성방법
AsyncTask를 상속받았을 경우 Generics로 3가지 인자값을 지정해주어야 한다.
AsyncTask<Params, Progress, Result>
- Params : AsyncTask가 실행시 execute(p1, p2 ...); 메소드를 통해서 넘겨주는 값을 선언
- Progress : doInBackground 메소드를 통해서 실행되는 publishProgress(p) 메소드의 인자값으로 넘길 값이다.
또한 오버라이딩한 onProgressUpdate(Progress p) 메소드의 인자값으로 넘겨주게 되는 값이다.
- Result : doInBackground 메소드를 통해서 리턴되고, onPostExecute(Result r) 메소드의 인자값으로 들어오게 되는 값이다.
(2) 주요 메소드
- protected abstract Result doInBackground(Params... params); (필수 구현 메소드)
- protected void onPostExecute(Result result) 결과값을 가지고 처리하고 싶은 일을 실행하는 메소드
- protected void onProgressUpdate(Progress... values) 진행중에 해당하는 값을 가지고 처리하고 싶은 일을
실행하는 메소드(일반적으로 프로그레스바의 값을 증가시키기 위해 사용)
(3) 실행 순서
- onPreExecute() -> doInBackground() ->
publishProgress() 를 통해서 넘어온 값으로 onProgressUpdate()가 실행 -> onPostExecute()
(4) 사용예제 (안드로이드 AsyncTask JavaDoc에 나온 예제)
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
실 사용예제 - xmlParser와 같이 사용
package com.example.netapp;
import java.io.*;
import java.util.*;
import org.apache.http.*;
import org.apache.http.client.entity.*;
import org.apache.http.client.methods.*;
import org.apache.http.impl.client.*;
import org.apache.http.message.*;
import org.apache.http.params.*;
import org.xmlpull.v1.*;
import android.app.*;
import android.os.*;
import android.util.*;
import android.widget.*;
public class BoardActivity extends ListActivity {
private ProgressDialog dialog;
protected ArrayList<Map<String, String>> dataList;
private AsyncTask<Void, Integer, Void> mTask = new AsyncTask<Void, Integer, Void>() {
protected Void doInBackground(Void... p) {
// 새롭게 데이터를 가져오는 부분(기존 List는 삭제)
dataList = new ArrayList<Map<String,String>>();
try {
publishProgress(1); // 접속 중
// 5초가 지나면 타임아웃 시킨다. 설정하지 않으면 계속 기다림
HttpParams params = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(params, 10000);
DefaultHttpClient client = new DefaultHttpClient(params);
// POST 방식으로 요청을 보내기 위해 요청주소를 인자값으로 객체 생성
HttpPost request =
// new HttpPost("http://14.37.37.161:8080/main2.xml");
new HttpPost("http://14.37.37.166:8080/sp/re/xml");
ArrayList<BasicNameValuePair> parameters =
new ArrayList<BasicNameValuePair>();
// 인자값을 ArrayList로 저장
parameters.add(new BasicNameValuePair("id", "완쌤"));
// 요청 객체(HttpPost)에 파라미터를 인코딩해서 저장
request.setEntity(
new UrlEncodedFormEntity(parameters, "UTF-8"));
publishProgress(2); // 데이터 수신 중
// 요청을 실행해서 응답을 받는다.
HttpResponse response = client.execute(request);
InputStream is = response.getEntity().getContent();
// XMLPullParser 이용 파싱
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser parser = factory.newPullParser();
parser.setInput(is, "UTF-8");
publishProgress(3); // 데이터 분석중
int event = XmlPullParser.START_DOCUMENT;
while((event = parser.next())!=XmlPullParser.END_DOCUMENT) {
switch(event) {
case XmlPullParser.START_TAG:
// item 태그가 아니면 건너뛴다.
if(!parser.getName().equals("item"))
break;
String title = parser.getAttributeValue(null, "title");
String wdate= parser.getAttributeValue(null, "wdate");
HashMap<String, String> map = new HashMap<String, String>();
map.put("title",title);
map.put("wdate",wdate);
dataList.add(map);
}
}
} catch (Exception e) {
publishProgress(-1);
Log.e("net","게시판 오류",e);
}
return null;
}
protected void onProgressUpdate(Integer[] values) {
switch(values[0]) {
case -1:
Toast.makeText(getApplicationContext(), "통신 오류", 0).show();
break;
case 1:
dialog.setMessage("접속 중...");
break;
case 2:
dialog.setMessage("데이터 수신 중...");
break;
case 3:
dialog.setMessage("데이터 분석 중...");
break;
}
dialog.setProgress(values[0]);
}
protected void onPostExecute(Void result) {
SimpleAdapter adapter = new SimpleAdapter(
getApplicationContext(), dataList,
android.R.layout.simple_list_item_2,
new String[]{"title","wdate"},
new int[]{android.R.id.text1,android.R.id.text2});
setListAdapter(adapter);
dialog.dismiss();
Toast.makeText(getApplicationContext(), "로딩완료", 0).show();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);
// ProgressDialog 띄워서 1~100까지 게이지를 채우고 사라질 것.
dialog = new ProgressDialog(this);
dialog.setTitle("Loading...");
dialog.setMessage("접속 시작");
dialog.setCancelable(false);
dialog.setMax(3);
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.show();
mTask.execute();
}
}
'Dev. 안드로이드 > 참고소스' 카테고리의 다른 글
[안드로이드 예제] Service & Notification(알림바띄우기) 이용하기 (2) | 2012.11.29 |
---|---|
[안드로이드 예제] BroadcastReceiver 이용하기 (3) | 2012.10.26 |
[안드로이드 예제] onSaveInstanceState() 메서드에 사용자 정의 클래스를 포함하는 Arraylist 담기 (0) | 2012.10.23 |
[안드로이드 팁] Android 기기별 액정 해상도 알아내기 (0) | 2012.10.22 |
안드로이드 환경설정(Preferences) 사용하기 (0) | 2012.07.26 |