=================================
=================================
=================================
출처: http://jo.centis1504.net/?p=966
자바의 Swing에서도 마찬가지이지만, 같은 스레드에서 시간이 걸리는 처리를 실행하게 되면 UI가 멈추거나 유져가 입력한 처리를 바로 개시하지 못하는 경우가 많다.
Android에서는 이런 처리들을 AsyncTask 로 정의하여 메인 스레드와 별도로 백그라운드에서 처리한다. (보통 Thread를 Androind에 최적화하여 Interface를 정의했다고 보면 될듯)
클래스에 지정하는 3개의 Generic의미는 첫번째가 doInBackground 의 인수, 두번째가 progress의 인수, 세번째가 결과(리턴)값의 인수이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
class SampleAsyncTask extends AsyncTask < Long , Integer , Float > {
@ Override
protected Float doInBackground ( Long . . . params ) {
// TODO 실제 백그라운드에서 처리할 내용을 구현한다.
if ( this . isCancelled ( ) ) {
// 비동기작업을 cancel해도 자동으로 취소해주지 않으므로,
// 작업중에 이런식으로 취소 체크를 해야 한다.
return null ;
}
// 작업진행률 (%)
publishProgress ( 100 ) ;
return null ;
}
@ Override
protected void onCancelled ( ) {
// TODO 작업이 취소된후에 호출된다.
super . onCancelled ( ) ;
}
@ Override
protected void onCancelled ( Float result ) {
// TODO 취소할때 지정한 결과값으로 취소를 한다.
super . onCancelled ( result ) ;
}
@ Override
protected void onPostExecute ( Float result ) {
// TODO 작업 종료후에 호출되지만, cancel할 경우에는 호출되지 않는다.
super . onPostExecute ( result ) ;
}
@ Override
protected void onPreExecute ( ) {
// TODO 작업 시작전에 호출된다.
super . onPreExecute ( ) ;
}
@ Override
protected void onProgressUpdate ( Integer . . . values ) {
// TODO 작업진행상황이 갱신되었을때 호출된다.
super . onProgressUpdate ( values ) ;
}
}
이렇게 정의하고 실제 호출할때는
SampleAsyncTask task = new SampleAsyncTask(“taskA”); task.execute((Long)1);
과 같이 백그라운드에서 실행한다.
실행중인지의 체크 방법
if ( myAsyncTask . getStatus ( ) == AsyncTask . Status . RUNNING ) {
// TODO 실행중인경우
}
This entry was posted in
Android . Bookmark the
permalink .
=================================
=================================
=================================
출처: http://stackoverflow.com/questions/9671546/asynctask-android-example
public class AsyncTaskActivity extends Activity { Button btn; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btn = (Button) findViewById(R.id.button1); btn.setOnClickListener((OnClickListener) this); } public void onClick(View view){ new LongOperation().execute(""); } private class LongOperation extends AsyncTask<String, Void, String> { @Override protected String doInBackground(String... params) { for(int i=0;i<5;i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } TextView txt = (TextView) findViewById(R.id.output); txt.setText("Executed"); return null; } @Override protected void onPostExecute(String result) { } @Override protected void onPreExecute() { } @Override protected void onProgressUpdate(Void... values) { } } }
=================================
=================================
=================================
출처: http://arabiannight.tistory.com/entry/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9CAndroid-AsyncTask-%EC%82%AC%EC%9A%A9%EB%B2%95
안드로이드/Android AsyncTask 사용법
안드로이드 AsyncTask 사용법에 대해 알아 보겠습니다. 안드로이드에는 UI 를 총괄하는 메인Thread가 존재 한고 있는데요.( [ 안드로이드/Android Android에서 Thread(쓰레드) 란 무엇 인가? ] ) 메인Thread 외에는 일반Thread들이 안드로이드 UI 화면을 처리할 수 없습니다. 그렇기 때문에 메인Thread와 일반Thread 를 잘 핸들링 해서 사용해야 하는데, 여간 번거로운 일이 아닙니다.
그렇기 때문에, Android 에서는 AsyncTask 라는 객체를 지원하는데요. AsyncTask는 UI 처리 및 Background 작업 등 을 하나의 클래스에서 작업 할 수 있게 지원해 줍니다. 쉽게말해 메인Thread와 일반Thread를 가지고 Handler를 사용하여 핸들링하지 않아도 AsyncTask 객체하나로 편하게 UI를 수정 할 수 있고, Background 작업을 진행 할 수 있습니다. 각각의 주기마다 CallBack 메서드를 사용해서 말이죠.
큰 장점입니다.
자 그럼 예제 소스를 살펴 볼까요?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package
arabiannight.tistory.com.aynctask;
import
android.app.Activity;
import
android.os.AsyncTask;
import
android.os.Bundle;
import
android.util.Log;
public
class
TestAsyncTaskActivity
extends
Activity {
private
MyAsyncTask myAsyncTask;
@Override
public
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.main);
myAsyncTask =
new
MyAsyncTask();
myAsyncTask.execute(
"80"
,
"90"
,
"100"
,
"110"
);
}
public
class
MyAsyncTask
extends
AsyncTask<string,
void
,=
""
string=
""
> {
@Override
protected
void
onPreExecute() {
super
.onPreExecute();
}
@Override
protected
String doInBackground(String... params) {
String sum =
""
;
if
(params !=
null
){
for
(String s : params){
sum += s;
}
}
return
sum;
}
@Override
protected
void
onPostExecute(String result) {
super
.onPostExecute(result);
if
(result !=
null
){
Log.d(
"ASYNC"
,
"result = "
+ result);
}
}
@Override
protected
void
onCancelled() {
super
.onCancelled();
}
}
}
1. onPreExecute() : Background 작업 시작전에 UI 작업을 진행 한다.
@Override protected void onPreExecute() { super.onPreExecute(); }
2. doInBackground() : Background 작업을 진행 한다.
@Override protected String doInBackground(String... params) { super.onPreExecute(); }
3. onPostExecute() : Background 작업이 끝난 후 UI 작업을 진행 한다.
@Override protected void onPostExecute(String result) { super.onPreExecute(); }
FLOW를 살펴 보자면,
[ on PreExecute()] -> [doInBackground()] -> [
onPostExecute()] 순서가 됩니다.
=================================
=================================
=================================
출처: http://daehyub71.tistory.com/entry/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9CAsyncTask%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC
AsyncTask를 이야기하려다 보니 프로그래스바 하나 넣어보겠다고 3~4일을 고생해서 겨우 찾아냈던 기억이 새록새록하면서 애증이 담겨있는 class라는 생각이 듭니다. 하지만 AsyncTask는 thread+handler라는 나름 강력한 기능을 가지고 있어서 제대로만 알아두면 유용한 클래스가 되지 않을까 싶습니다.
혹시 책만 보고 도전했다가 저같이 고생하지 않았으면 하는 맘에 이 글을 적어봅니다.
왜 AsyncTask인가?
AsyncTask라는 클래스 이름은 Asynchronous Task의 줄임이며, UI스레드의 입장에서 볼 때 비동기적으로 작업이 수행되기 때문에 붙여진 이름이다.
sync 와 async의 용어는 네트워크이나 커널 프로세스에서 많이 나오는 용어인데요.저야 뭐 이론적으로는 공부한지 하도 오래되어서 그냥 프로그램 하면서 경험으로 이야기를 해보겠습니다.
보통 sync는 직렬회로라고 보시면 될듯합니다. 반면 async는 병렬회로라고 보시면 될 듯 합니다.
일이 순차적으로 진행되면서 하나가 해결되면 그다음 일이 진행되는 식으로 네트워크에서는 요청(request)를 보내면 항상 응답(response)을 받아야 진행하는 방식으로 구현하면 sync방식,아니고 계속 요청을 보내는 통로와 응답을 받는 통로를 따로 만들어두면 async방식이라고 불리죠.
AsyncTask는 UI 처리 및 Background 작업 등 을 하나의 클래스에서 작업 할 수 있게 지원해 줍니다. 쉽게말해 메인Thread와 일반Thread를 가지고 Handler를 사용하여 핸들링하지 않아도 AsyncTask 객체하나로 각각의 주기마다 CallBack 메서드가 편하게 UI를 수정 할 수 있고, Background 작업을 진행 할 수 있습니다.
AsyncTask사용법
Object로부터 상속하는 AsyncTask는 Generic Class이기 때문에 사용하고자 하는 type을 지정해야 합니다. AsyncTask클래스는 기본적으로 3개의 제네릭 타입(Params,Progress,Result)을 제공하고 있는 추상 클래스다.Generic type은 실행시간에 데이터 타입을 정할 수 있는 특수한 타입이라고 이해하시면 될 듯 합니다.
Params: background작업 시 필요한 data의 type 지정 Progress: background 작업 중 진행상황을 표현하는데 사용되는 data를 위한 type 지정 Result: 작업의 결과로 리턴 할 data 의 type 지정
예)
1
AsyncTask<DataInfo[], Integer, Void> InsertTask =
new
InsertCallTask().execute(datainfo4);
미사용 타입에 대해서는 Void를 전달하면 된다.
AsyncTask Callbak 함수
언제 호출되여 무슨 작업을 하는가와 함께 각 메서드가 어떤 스레드에서 실행되는가도 중요하다. doInBackground메서드 외에는 모두 UI스레드에서 실행되므로 메인스레드의 view들을 안전하게 참조할 수 있습니다.
주로 쓰게 되는 콜백메스드 4개에 대해 설명해보겠습니다.
● void onPreExecute()
작업이 시작되기 전에 호출되며 UI스레드에서 실행되는 메소드,계산을 위한 초기화나 프로그래스 대화상자를 준비하는 등의 작업을 수행합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Override
protected
void
onPreExecute() {
dialog =
new
ProgressDialog(DetailActivity.con);
dialog.setTitle(
"이미지 다운로드중"
);
dialog.setMessage(
"잠시만 기다리세요..."
);
dialog.setIndeterminate(
true
);
dialog.setCancelable(
true
);
dialog.show();
super
.onPreExecute();
}
● Result doInBackground(Params... params)
백그라운드 스레드로 동작해야 하는 작업을 실행한다. execute메서드로 전달한 data tye이 params 인수로 전달되는데 여러개의 인수를 전달할 수 있으므로 배열 타입으로 되어 있습니다. 그래서 하나의 인수만 필요하다면 params[0]만 사용하면 됩니다. 작업 중에 publishProgress 메소드를 호출하여 작업 경과를 UI스레드로 display할 수 있으며 작업결과는 Result타입으로 리턴됩니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
@Override
protected
Bitmap doInBackground(String... urls) {
final
HttpClient client = AndroidHttpClient.newInstance(
"Android"
);
final
HttpGet getRequest =
new
HttpGet(urls[
0
]);
final
int
IMAGE_MAX_SIZE =
1280
;
try
{
HttpResponse response = client.execute(getRequest);
final
int
statusCode = response.getStatusLine().getStatusCode();
if
(statusCode != HttpStatus.SC_OK)
{
return
null
;
}
final
HttpEntity entity = response.getEntity();
if
(entity !=
null
)
{
InputStream inputStream =
null
;
try
{
inputStream = entity.getContent();
BitmapFactory.Options bfo =
new
BitmapFactory.Options();
bfo.inJustDecodeBounds =
true
;
BitmapFactory.decodeStream(
new
FlushedInputStream(inputStream),
null
, bfo);
if
(bfo.outHeight * bfo.outWidth >= IMAGE_MAX_SIZE * IMAGE_MAX_SIZE)
{
bfo.inSampleSize = (
int
)Math.pow(
2
, (
int
)Math.round(Math.log(IMAGE_MAX_SIZE / (
double
) Math.max(bfo.outHeight, bfo.outWidth)) / Math.log(
0.5
)));
}
bfo.inJustDecodeBounds =
false
;
response = client.execute(getRequest);
final
int
nRetryStatusCode = response.getStatusLine().getStatusCode();
if
(nRetryStatusCode != HttpStatus.SC_OK)
{
return
null
;
}
final
HttpEntity reEntity = response.getEntity();
if
(reEntity !=
null
)
{
InputStream reInputStream =
null
;
try
{
reInputStream = reEntity.getContent();
final
Bitmap imgBitmap = BitmapFactory.decodeStream(
new
FlushedInputStream(reInputStream),
null
, bfo);
return
imgBitmap;
}
finally
{
if
(reInputStream !=
null
)
{
reInputStream.close();
}
reEntity.consumeContent();
}
}
}
finally
{
if
(inputStream !=
null
)
{
inputStream.close();
}
entity.consumeContent();
}
}
}
catch
(IOException e)
{
getRequest.abort();
}
catch
(IllegalStateException e)
{
getRequest.abort();
}
catch
(Exception e)
{
getRequest.abort();
}
finally
{
if
((client
instanceof
AndroidHttpClient))
{
((AndroidHttpClient)client).close();
}
}
return
null
;
}
● void onProgressUpdate(Progress... values)
doInBackground에서드에서 publishProgress(Progress...) 메소드를 호출할 때 호출되며 작업의 진행사항을 표시하기 위해 호출됩니다. UI스레드에서 프로그래스바에 진행 상태 표시하는 역할 수행합니다.
1
2
3
4
5
protected
void
onProgressUpdate(Integer... progress) {
Log.d(
"LOST"
,
"onProgressUpdate:["
+progress[
0
]+
"]"
);
dialog.setProgress(progress[
0
]);
}
● void onPostExecute(Result result)
doInBackground에서드의 작업 결과를 UI반영하는 역할을 담당하는 메소드입니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Override
protected
void
onPostExecute(Bitmap imgBitmap) {
if
(imgBitmap !=
null
)
{
imgView.setImageBitmap(imgBitmap);
imgView.setVisibility(ImageView.VISIBLE);
textview.setVisibility(TextView.GONE);
}
else
{
textview.setText(
"등록된 사진이 없습니다."
);
textview.setTextSize(
20
);
textview.setGravity(Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL);
textview.setVisibility(TextView.VISIBLE);
imgView.setVisibility(ImageView.GONE);
}
dialog.dismiss();
}
일반적으로
AsyncTask를 구현할 때 별도 스레드로 동작해야 할 코드는 doInBackground()메소드에 작성하고, 이 메소드가 실행되기 전에 먼저 처리할 코드가 있다면 onPreExecute()메소드에 작성하면 됩니다. 그리고 doInBackground()메소드가 완료된 후에 처리해야할 코드는 onPostExecute()메소드에 작성하고, doInBackground()메소드가 동작하는 동안 주기적으로 반영해야 할 작업이 있다면 onProgressUpdate()메소드에 작성하면 됩니다.
이 때 주의사항은 3개의 제네릭 타입과 메소드 타입을 잘 맞춰어야 원하는 결과가 나온다는 겁니다. 이게 잘 안 맞아서 저는 코딩하면서 구현이 제대로 안되고 한참 고생했던 기억이 있습니다. 꼭 doInBackground, onPreExecute, onPostExecute의 리턴값과 파라미터를 잘 매칭해야 합니다.
참고사이트
=================================
=================================
=================================
출처: http://ismydream.tistory.com/130
안드로이드 비동기 처리하기 AsyncTask
비동기 처리를 하기 위해서는 별도의 Thread 를 생성하여 public void run() 메소드를 구현하면 되지만 안드로이드에서는 직접 Thread 를 생성하기 보다는 AsyncTask 를 사용하길 권장합니다.
AsyncTask 내부에는 자체 ThreadPool 이 있어 Thread 가 무한정 늘어나 메모리에 부담을 주지 않도록 관리 하고 있기 때문에 따로 ThreadPool 을 관리하지 않는다면 AsyncTask 를 사용하는게 무난할 것 같습니다.
아래는 비동기적으로 ImageView에 Bitmap을 로드하는 코드입니다.
doInBackground 메소드는 기존의 Thread 에서의 run() 메소드라고 보시면 됩니다.
AsyncTask 는 처리할 데이터에 따라 파라미터 타입을 정의할 수 있습니다. 정의하는 부분은 클래스를 정의하는 부분에 있습니다.
class BitmapWorkerTask extends AsyncTask< Integer, Void, Bitmap >{
Integer
execute, doInBackground 의 파라미터 타입
Void
onProgressUpdate 의 파라미터 타입
Bitmap
doInBackground 의 리턴값, onPostExecute 의 파라미터 로 설정됩니다.
AsyncTask 소스를 보면 좀더 정확히 확인하실 수 있습니다.
또한 AsyncTask 는 실행 전후로 전처리, 후처리를 할 수 있는 콜백 메소드를 제공합니다.
onPreExecute(), onPostExecute( Bitmap)
class BitmapWorkerTask extends AsyncTask< Integer, Void, Bitmap >{
private final WeakReference<ImageView> imageViewReference;
private int data = 0;
public BitmapWorkerTask( ImageView imageView){
// WeakReference 를 사용하는 이유는 image 처럼 메모리를 많이 차지하는 객체에 대한 가비지컬렉터를 보장하기 위해서입니다.
imageViewReference = new WeakReference<ImageView>(imageView);
}
@Override
protected Bitmap doInBackground( Integer ... params){
data = param[0];
return decodeSampledBitmapFromResource( getResources(), data, 100, 100);
}
@Override
protected void onPostExecute( Bitmap bitmap){
if( imageReference != null && bitmap != null){
final ImageViewReference imageView = imageViewReference.get();
if( imageView != null){
imageView.setImageBitmap( bitmap);
}
}
}
}
위처럼 AsyncTask 를 확장하는 클래스를 생성한후 실행하면 됩니다.
public void loadBitmap( int resId, ImageView imageView){
BitmapWorkerTask task = new BitmapWorkerTask( imageView);
task.execute( resId);
}
AsyncTask 는 execute( Runnable) 메소드도 제공하기 때문에 별도의 스레드 작업을 할때도 사용할 수 있습니다.
[별도의 카메라 앱을 실행시켜 사진을 촬영하는 코드]
AsyncTask.execute( new Runnable(){
public void run() {
Intent openCameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
try{
mImageF = createImageFile();
// 이미지가 저장될 파일은 카메라 앱이 구동되기 전에 세팅해서 넘겨준다.
openCameraIntent.putExtra( MediaStore.EXTRA_OUTPUT, Uri.fromFile( mImageF));
mActivity.startActivityForResult( openCameraIntent, RequestCodes.REQUESTCODE_CAMERA_PICTURE);
}catch( IOException e){
e.printStackTrace();
}
}
});
=================================
=================================
=================================