2010년 12월 30일 목요일

[Android강좌][Korean][테마][Thread] - AsyncTask





보통 Thread 사용 시, 아래와 같이 많이 사용을 하였습니다.
첫째는 Thread 클래스를 subclassing하는 새 객체를 정의해고 Thread:run() 메소드를 오버라이딩 하는 방법이고,
둘째는 new 연산자로 새로운 Thread 객체를 생성하면서 생성인자로 Runnable 인터페이스(스레드에서 실행될 logic포함)를 전달하는 방식입니다.

위의 방법은 Logic이 복잡해지면, 관리가 힘들어지는 것 같습니다.
그래서 다른 방법을 찾던 도중 새로운 Class 하나를 찾았습니다.
바로 “AsyncTask” Class 입니다.


AsyncTask (Asynchronous Task) - [Overview]

: 안드로이드에서는 Background작업에 관한 모든 사항(스레드 객체 생성, 사용, UI스레드와 통신 등)Activity 코드에 포함 되고 특히 background 스레드가 UI 위젯과 빈번한 통신을 할수록 Activity 코드의 복잡함은 점점 배가 되기 때문에, 해당 문제를 해결하기 위해 API level 3 (1.5 version) 부터 AsyncTask라는 클래스를 제공하고 있다고 합니다.

: AsyncTask클래스는 background작업을 위한 모든 일(스레드생성, 작업실행, UI와 통신 등)을 추상화 함으로 각각의 background작업을 객체 단위로 구현 및 관리를 편리할 수 있게 하는 것이 목적임.

AsyncTask (Asynchronous Task) - Usage











: AsyncTask의 상속관계를 보면,
Object로부터 상속하는 AsyncTask는 Generic Class이기 때문에 사용하고자 하는 type을 지정해야 한다. AsyncTask클래스의 사용시 지정해야 하는 generic type은 각각 다음의 용도로 사용된다.
    - Params: doInBackground()  data의 type 지정
    - Progress: onProgressUpdate() data를 위한 type 지정
    - Result: onPostExecute() data 의 type 지정

- AsyncTask Class Base.
private class receiveRollback extends AsyncTask<Object, Object, Object> {

  // UI Thread AsynchTask 에 의해 맨 처음 실행되는 CallBack
  protected void onPreExecute() {
  }

  // UI Thread AsynchTask 에 의해 실제 작업이 이루어지는 CallBack
  protected String doInBackground(Object... params) {
    return result;
  }

  // onInBackground 작업 진행 상황을 표시하기 위한 CallBack
  protected void onProgressUpdate(Object... progress) {
  }

  // onInBackground이 완료되면 자동으로 실행되는 CallBack
  protected void onPostExecute(Object result) {
  }

  // onInBackground이 작업이 취소될때 실행되는 CallBack
  protected void onCanelled(){
  }
}



※ 주의 사항
: AsyncTask클래스는 항상 subclassing 하여 사용하여야 한다.

2) AsyncTask 인스턴스는 항상 UI 스레드에서 생성한다.

3) AsyncTask:execute(…) 메소드는 항상 UI 스레드에서 호출한다.

4) AsyncTask:execute(…) 메소드는 생성된 AsyncTask 인스턴스 별로 꼭 한번만 사용 가능하다. 같은 인스턴스가 또 execute(…)를 실행하면 exception이 발생하며, 이는 AsyncTask:cancel(…) 메소드에 의해 작업완료 되기 전 취소된 AsyncTask 인스턴스라도 마찬가지이다. 그럼으로 background 작업이 필요할 때마다 new 연산자를 이용해 해당 작업에 대한 AsyncTask 인스턴스를 새로 생성해야 한다.

5) AsyncTask의 callback 함수 onPreExecute(), doInBackground(…), onProgressUpdate(…), onPostExecute(…)는 직접 호출 하면 안 된다. (꼭 callback으로만 사용)

[Example Test Code]
1. main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
 <ProgressBar
  android:id="@+id/progressbar"
  style="?android:attr/progressBarStyleHorizontal"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:paddingBottom="20px" />

 <TextView 
  android:id="@+id/result"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:text="Result"
     android:paddingBottom="20px" />
    
    <Button
     android:id="@+id/executetask"
     android:layout_height="wrap_content"
     android:layout_width="wrap_content"
     android:text="AsyncTask Start" />
   
</LinearLayout>

2. main.java
package com.Example_AsyncTask;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
public class main extends Activity {
 ProgressBar m_progressBar = null;
 TextView m_Result = null;
 Button m_ExecuteTask = null;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        m_progressBar = (ProgressBar)findViewById(R.id.progressbar);
        m_Result = (TextView)findViewById(R.id.result);
        m_ExecuteTask = (Button)findViewById(R.id.executetask);
       
        m_ExecuteTask.setOnClickListener(new OnClickListener(){
   @Override
   public void onClick(View arg0) {
    // TODO Auto-generated method stub
    new ExampleAsyncTask().execute("1","2","3","4","5","6");
   }
       
        });
    }
   
   
    private class ExampleAsyncTask extends AsyncTask<String, Integer, Long> {     
     // UI Thread AsynchTask 에 의해 맨 처음 실행되는 CallBack
     @Override
  protected void onPreExecute() {
      m_Result.setText("Background Thread Start");
   super.onPreExecute();
  }
     // UI Thread AsynchTask 에 의해 실제 작업이 이루어지는 CallBack
  @Override
     protected Long doInBackground(String... strData) {
   long result = 0;
      int numberOfParams = strData.length;
   
      for(int i=0; i<numberOfParams; i++) {   
       SystemClock.sleep(1000);
       // onProgressUpdate callback
       publishProgress((int)(((i+1)/(float)numberOfParams)*100));
      }   
      return result;
     }
   
  // onInBackground 작업 진행 상황을 표시하기 위한 CallBack
     @Override
     protected void onProgressUpdate(Integer... progress) {
      m_progressBar.setProgress(progress[0]);
     }
   
     // onInBackground이 완료되면 자동으로 실행되는 CallBack
     @Override
     protected void onPostExecute(Long result) {
      m_Result.setText("Background Thread End");
     }
   
     // onInBackground이 작업이 취소될때 실행되는 CallBack
     @Override
  protected void onCancelled() {
   // TODO Auto-generated method stub
   super.onCancelled();
  }   
    }
}


=> Example Source Code가 필요하시면,메일로 연락주세요.

댓글 없음:

댓글 쓰기