[android] AsyncTask too late problem..

안드로이드 AsyncTask

android AsyncTask 는 안드로이드에서 자주쓰고, 자주 보는 클래스이다.

우리 회사에서 서비스중인 안드로이드 앱에서도 AsyncTask를 많이 쓰고 있다.

그런데, 회사에서 서비스 중인 안드로이드가 너무 느려서 원인을 찾기위해 이것저것 로그를 찍어본 결과.
AsyncTask를 실행하고, doInBackground() 호출이 너무 느렸다. 무려 3초에서 4초정도 딜레이가 되고 있었다.

원인을 열심히 찾아봤는데 허니콤 이전 버전에선 AsyncTask의 개수제한이 있었다.

core pool size와 max pool size가 있었던것 같은데, 필요하면 아래 글 참고 하면 될듯.

AsyncTask 참고1
AsyncTask 참고2

수정하려고 봤더니 여기저기 AsyncTask를 마구마구 쓰고 있고, 여러 depth에 걸처서 부르는 로직도 있어서 수정 규모가 너무 크다고 판단.

일단 심플하게 thread를 이용해서 AsyncTask역할을 그대로 하는 코드를 만들었다.

Why?

AsyncTask 자리에 그대로 바꿔치기 하기 위함이다.
일단 이것으로 속도확보를 했으니 다음 차례는 쓰레드 풀이든 스케쥴링이던 하면 될 듯하고. 일단 지금은 스케쥴러를 별도로 만들어 관리하도록 수정.

혹시 몰라서 여기에 올려놓는다. 자료 백업 목적 및 필요한 사람들이 있을지도 모르니 공유의 목적도…

/****
 * title: AsyncThread
 * description: Simple thread extension like AsyncTask. 
 * 				But the AsyncThread is non atomic no use thread pool.
 *
 * author: weep
 * blog: weeppp.com
 * email: ktg@weeppp.com
 * Copyright (c) 2015 Teukgeon, Kwon. All rights reserved.
 ****/

package com.weeppp.tklib;

import android.os.Handler;
import android.os.Message;

public abstract class AsyncThread<Params, Progress, Result> extends Thread implements Runnable {
    protected void onPreExecute() {};
    abstract protected Result doInBackground(Params... params);
    protected void onPostExecute(Result result) {};
    protected void onCancell() {};

    Params[] params;
    static final int MESSAGE_POST_RESULT = 30;

    enum Status {
        PENDING,
        RUNNING,
        FINISHED
    }

    private Status status = Status.PENDING;
    private boolean isCancel = false;
    final InternalHandler internalHandler = new InternalHandler();

    public AsyncThread()
    {

    }

    public AsyncThread<Params, Progress, Result> execute(Params... params)
    {
        if (status != Status.PENDING) {
            switch (status) {
                case RUNNING:
                    throw new IllegalStateException("Cannot execute task:"
                            + " the task is already running.");
                case FINISHED:
                    throw new IllegalStateException("Cannot execute task:"
                            + " the task has already been executed "
                            + "(a task can be executed only once)");
                default:
                    break;
            }
        }
        status = Status.RUNNING;

        this.params = params;
        onPreExecute();
        start();
        return this;
    }

    public final Status getStatus() {
        return status;
    }

    public final boolean isCancelled() {
        return isCancel;
    }

    public final boolean cancel() {
        isCancel = true;
        return isCancel;
    }

    public final boolean cancel(boolean mayInterruptIfRunning) {
        isCancel = true;
        return isCancel;
    }

    public void run()
    {
        final Result result = doInBackground(params);

        Message msg = internalHandler.obtainMessage(MESSAGE_POST_RESULT);
        msg.obj = new AsyncResult(this, result);
        internalHandler.sendMessage(msg);
    }

    protected void onCancell(Result result)
    {
        onCancell();
    }

    private void finish(Result result)
    {
        if (isCancelled()) {
            onCancell(result);
        }
        else {
            onPostExecute(result);
        }
        status = Status.FINISHED;
    }

    private static class InternalHandler extends Handler {
        @SuppressWarnings({"unchecked"})
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MESSAGE_POST_RESULT:
                    AsyncResult aResult = (AsyncResult)msg.obj;
                    aResult.thread.finish(aResult.result);
                    break;
            }
        }
    }

    @SuppressWarnings({"rawtypes"})
    static class AsyncResult {
        final AsyncThread thread;
        final Object result;
        public AsyncResult(AsyncThread thread, Object result)
        {
            this.thread = thread;
            this.result = result;
        }
    }
}