AsyncTask 와 Loader

4 분 소요

HTTP와 JSON Parsing

HTTP와 JSON을 음식 주문에 비교해 보도록 하자.

  • 파스타 식당에 가서 “토마토 파스타”를 주문한다고 하자. 이 때 이 주문 정보가 “adress”이다.
  • 웨이터는 이 주문 정보를 이용해서 주문에 들어간다. 웨이터는 “main thread”에 당신이 주문한 음식을 요구한다.
  • 웨이터가 당신의 음식을 요구하고 음식이 나올 때까지, 당신은 “background thread”에서 물을 마시는 등 다른 행동을 할 수 있다.
  • 파스타가 나오면 당신은 그것을 마음대로 할 수 있다. 이 때 파스타가 JSON 정보이고 마음대로 하는 것이 parsing이다.

AsyncTask

Main thread(UI thread)와 Background thread를 사용하려면 AsyncTask라는 abstract class를 반드시 이용해야 한다.

가장 많이 사용될 callback method에 대해 알아보자.

  • onPreExecute(): background thread에서 코드가 돌아가기 전에 실행되야 할 내용을 적어준다. main thread에서 실행.

  • doInBackground(Params…): background thread에서 실행될 코드를 입력. background thread에서 실행된다. return result하여 onPostExecute로 넘겨 준다. publishProgress() 를 콜 할수있다.

  • onProgressUpdate(Progress…): doInBackground()에서 publicshProgress()를 call했다면, 해당 return값을 받아서 doInBackground()가 실행되는 동안 실행된다. main thread에서 실행. 따라서 유저에게 progress를 보여줄 수 있다.

  • onPostExecute(Result): doInBackground()가 종료된 이후, return값을 받아 실행된다. main thread.

참고 링크: 클릭

Loader와 LoaderManager.LoaderCallbacks 인터페이스

Loader LoaderManager.LoaderCallbacks

AsyncTask는 멀티쓰레드를 쓸 수 있게 해주지만 단점이 있는데.. 화면전환같이 액티비티가 리셋되면 똑같은 짓을 또 한다는 거다. 그럼 그 때마다 AsyncTask instance가 만들어져야 하고 엄청난 낭비를 하게 되는데..

이를 효율적으로 조절해주는게 바로 Loader다

참고 링크: 클릭

Loader를 관리하는 LoaderManager interface가 있는데. LoaderManager는 Activity와 상호작용하며 하나 또는 그 이상의 Loader instance를 관리한다.

LoaderManager.LoaderCallbacks 인터페이스를 implement해야 한다. 이 인터페이스에 속한 method는 다음과 같다.

  1. onCreateLoader: Loader instance를 생성하고 return

  2. onLoadFinished: Loader가 data loading을 끝낸 후 data를 받아줌.

  3. onLoaderReset: 이전에 생성된 Loader가 더 이상 필요치 않을 때, 기존 데이타를 지워야 할 때 사용

로더는 고유한 ID를 가져야만 하고, LoaderManager는 ID를 통해 로더를 관리한다. 예를 들면 아래 initLoader메쏘드의 첫번쨰 인자는 로더의 ID인데, 화면로테이팅 등 새로 액티비티를 생성할 떄 기존 로더가 있는지 없는지 여부를 ID를 통해 파악하고, 없으면 새로 만들고 있으면 기존거를 갖다 쓴다. 이것이 AsynkTask와의 차이점이다.

로더를 시작하기 위해서는 onCreate()에 아래와 같이 쓰자.

// Prepare the loader.  Either re-connect with an existing one,
// or start a new one.
getSupportLoaderManager().initLoader(0, null, this);

참고링크클릭

AsyncTask 를 AsyncTaskLoader로 Refactor하자.

즉 그냥 AsyncTask는 잘 쓰지 않는 듯 하고, Loader를 쓰는 것 같다. Loader도 종류가 많은데 우리는 AsyncTask 대신에 쓸 거니까 AsyncTaskLoader를 쓴다.

기존의 AsyncTask가 했던 역할을 옮기기 위해서는 아래의 작업을 해야 한다.

  1. CustomLoader class 정의하기(AsyncTaskLoader의 subclass)

이 때 기존 AsyncTask의 doInBackground()내용이 loadInBackground() 로 옮겨와야 하고 (Background thread), onPostExcute()내용은 onLoadFinished()로 옮겨오면 된다.

(꼭 커스텀 로더를 만들 필요는 없다. AsyncLoader를 갖다 써도 됨..)

  1. MainActivity에 LoaderManager.LoaderCallbacks 인터페이스를 implement하기. 이를 통해서 위에 명시한 세 가지 method를 반드시 override해야한다.

  2. MainActivity의 onCreate에서 로드 시작하기 getSupportLoaderManager().initLoader(1, null, this).forceLoad();

사실 이부분은 너무 할 게 많고 복잡하다.. 깃헙의 T05b-02를 참조하자…클릭

댓글남기기