반응형
블로그 이미지
개발자로서 현장에서 일하면서 새로 접하는 기술들이나 알게된 정보 등을 정리하기 위한 블로그입니다. 운 좋게 미국에서 큰 회사들의 프로젝트에서 컬설턴트로 일하고 있어서 새로운 기술들을 접할 기회가 많이 있습니다. 미국의 IT 프로젝트에서 사용되는 툴들에 대해 많은 분들과 정보를 공유하고 싶습니다.
솔웅

최근에 받은 트랙백

글 보관함


Using the AsyncTask Class

 

이번 글에서는 쓰레드를 생성하고 관리하기 위해 AsyncTask 클래스를 사용하는 방법을 알아보겠습니다.
 기본적으로 AsyncTask 클래스는 백그라운드에서 프로세스를 실행하기 위해 비동기 task 를 생성합니다. 이 AsyncTask 클래스는 프로그레스를 보여주고 태스크를 완료하기 위해 쓰레드와 동기화 하는 여러개의 이벤트 핸들러들을 제공합니다. AsyncTask 는 여러 태스크드을 실행할 수 있습니다. 네트워크에서 데이터를 받아오고 백그라운드로 데이터를 저장하고 하는 일들을요.
 

AsyncTask에는 약간의 design flaw들이 있는데요. 이것들은 핸들러와 pool에 근거하고 한번에 몇개의 쓰레드만을 핸들링 할 수 있습니다. 왜냐하면 AsyncTask는 compatibility library에 포함되어 있기 때문이죠.


AsyncTask를 초기화하기 위해 AsyncTask 클래스를 extend 하고 파라미터를 제공합니다. 그 파라미터 들은 Input Parameters, Progress Values, Result Values 가 됩니다. 이 파라미터들을 전달하고 싶지 않으면 그냥 void 를 사용하시면 됩니다. 이 subclass는 아래의 이벤트 핸들러들을 override 해야 합니다.

- doInBackground : 이 메소드는 백그라운드 쓰레드에서 실행합니다. user와 interact 가 필요 없는 코드를 이 핸들러에 넣습니다. Input Parameter 가 이 메소드에 전달 될 겁니다. 이 메소드에서 publishProgress() 메소드가 호출되고 onProgressUpdate() 메소드가 메인 쓰레드안에서 실행 될 겁니다. 이 publishProgress() 와 onProgressUpdate() 메소드들을 사용해서 이 백그라운드 쓰레드는 메인 쓰레드와 communicate를 해 작업의 progress를 보여주기 위해 UI 엘리먼트 들을 업데이트 합니다. 이 메소드에서 작동하는 코드는 별도의 백그라운드 쓰레드에서 실행되는 것을 기억해 두세요.


- onProgressUpdate() : 이 핸들러를 override 해서 task 내에서 작업의 progress를 가리키기 위해 UI를 업데이트 합니다. 이 핸들러는 publishProgress()로 전달된 파라미터 세트를 받습니다. 이 핸들러는 실행이 되면 쓰레드와 동기화 됩니다. 그러니까 안전하게 UI 엘리먼트를 수정할 수 있습니다.


- onPostExecute : 이름에서 알 수 있듯이 이 메소드는 doInBackground() 메소드가 완료된 후에 호출 됩니다. doInBackground() 메소드에 의해 return 된 Result Value들은 이 메소드에 전달 됩니다. 이 핸들러는 비동기 task 가 완료 됐을 때 inform 될 수 있습니다.

이 AsyncTask 클래스는 두개의 콜백 메소드를 제공합니다.


- onPreExecute : 이름을 보면 알 수 있듯이, 이 메소드는 doInBackground() 메소드가 호출되기 전에 호출 됩니다. 이 메소드는 메인 쓰레드에서 작동되고 setup 같은 작업을 여기서 하게 됩니다.


- onCancelled : 쓰레드의 cancellation을 관리 합니다. 이 메소드는 쓰레드의 실행을 interrupt하고 onPostExcute() 메소드의 실행을 막습니다.


NOTE : onPostExecute, onPreExecute, onProgressUpdate, onCancelled를 오버라이드 하는 것은 선택사항 입니다. 반드시 오버라이딩을 해야만 하는 것은 아닙니다.


백그라운드 쓰레드에서 1에서 10까지의 숫자를 순서대로 표시하는 어플리케이션을 만들겠습니다.
이름은 AsyncTasksApp 입니다. 일단 화면에 숫자를 표시하려면 TextView를 만들어야 겠죠.


아래 activity_async_tasks_app.xml 파일이 있습니다.


<LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <TextView
        android:id="@+id/seqnums"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="@dimen/text_size"
        android:textStyle="bold"  />
</LinearLayout>


한 개의 TextView 만 있죠?


다음은 자바 파일을 보겠습니다.

AsyncTasksAppActivity.java


public class AsyncTasksAppActivity extends Activity {
    TextView seqNums;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_async_tasks_app);
        seqNums=(TextView) findViewById(R.id.seqnums);
        new PrintSequenceTask().execute(1);
    }

    private class PrintSequenceTask extends
        AsyncTask<Integer, Integer, Void> {
        @Override
        protected void onPreExecute() {
            seqNums.setText("Sequence numbers begins");
        }

        @Override
        protected Void doInBackground(Integer... args) {
            for (int i = args[0]; i <= 10; i++) {
                publishProgress(i);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... args) {
           seqNums.setText(args[0].toString());
        }

        @Override
        protected void onPostExecute(Void result) {
           seqNums.setText("Sequence numbers over");
        }
    }
}




딱 보면 PrintSequenceTask 클래스가 AsyncTask를 extends 한 것을 보실 수 있으실 겁니다. onCreate() 메소드를 보시면 이 클래스를 호출할 때 파라미터를 1을 전달했는데요. 그건 숫자를 1 부터 표시하기 위해 전달 한 겁니다.  이 PrintSequenceTask 클래스가 호출 된 후 doInBackground() 메소드가 실행되기 전데 onPreExecute() 메소드가 실행되서 Sequence numbers bigins 라는 텍스트를 화면에 뿌려 줄 겁니다. 그 다음에 doInBackground() 메소드가 실행되서 for 루프가 실행되겠죠. 아까 onCreate() 에서 1을 파라미터로 받았으니까 int i 는 1 부터 실행 될 겁니다. 1에서 10까지 for 루프가 돌면서 그 값들을 publishProgress()에 할당 합니다. 이 publishProgress() 메소드가 호출 되면 메인 쓰레드에서 onProgressUpdate() 메소드가 실행됩니다. 이 때 publishProgress() 에 전달 된 값이 그대로 onProgressUpdate()에도 전달이 됩니다. 그러니까 여기서는 1부터 10까지의 숫자가 전달이 되겠죠.


onProgressUpdate() 메소드에서는 TextView에 전달된 값을 표시하는 로직이 있네요. 1에서 10까지 숫자가 표시될 때 각각 1초간의 쉬는 시간이 있습니다. 최종적으로 doInBackground() 안의 작업이 끝나게 되면 즉 모든 숫자들이 다 표시되고 난 후 onPostExecute() 메소드가 실행됩니다. 여기서는 Sequence numbers over 라는 텍스트가 화면에 뿌려지도록 했습니다.

그러니까 전체적으로 보면 어플리케이션이 실행되면 Sequence numbers begins라는 글자가 화면에 표시되고 1부터 10까지의 숫자가 1초 간격으로 차례대로 표시되다가 마지막에는 Sequence numbers over 라는 텍스트가 표시 될 겁니다.


Summary

이 챕터에서는 어플리케이션의 퍼포먼스를 더 좋게 만드는 것과 관련해서 몇가지 다뤄봤습니다. dual-core chips와 quad-core 프로세서가 어플리케이션 experience를 더 좋게 만든다는 것도 다뤘구요. garbage collection이 더 이상 사용되지 않는 메모리를 새로운 어플리케이션에 할당한다는 내용도 배웠습니다. 또한 어플리케이션의 task를 쓰레드를 사용해서 백그라운드로 돌리는 절차에 대해서도 보셨습니다. 마지막으로 백그라운드에서 비동기적으로 태스크를 생성화고 관리하기 위해 AsyncTask 클래스를 어떻게 사용하는지에 대해서도 배웠습니다.

반응형

Comment