Android AsyncTask进度更新挂起

时间:2017-07-28 08:31:21

标签: java android multithreading android-asynctask

所以我在编写自己的AsyncTask类时遇到了麻烦,就像本机上运行在ThreadPoolExecutor上的系统一样。一切都很好,直到我决定实施进展的一面。进度非常类似AsyncTask,在UI线程上调用onProgressUpdate函数。我遇到的问题是,只要onProgressUpdate中有System.out或Log.x行,它就会无限期挂起,没有任何错误或警告。代码如下:

 public abstract class Task<A, B> {

    private static final Executor EXECUTOR = getExecutor();
    private static final int DEFAULT_PRIORITY = Thread.MIN_PRIORITY;
    private static final int DEFAULT_PROGRESS_INCREMENT = 1;

    private static final Executor getExecutor() {
        ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newCachedThreadPool();
        executor.setCorePoolSize(1);
        executor.allowCoreThreadTimeOut(false);
        // TODO set rejection handler
        //executor.setRejectedExecutionHandler(new Handler());
        // TODO set thread factory
        executor.prestartCoreThread();
        return executor;
    }

    public static class ExecutionListener<B> {

        public void onPreExecute() {
            Log.i("TASK", "Pre - Thread: " + Thread.currentThread().getId());
        }

        public void onPostExecute(B output) {

            Log.i("TASK", "Post - Thread: " + Thread.currentThread().getId() + " - Output: " + output);
        }

        public void onProgressUpdate(int progress) {
            Log.d("TASK", "Hello");
        }
    }

    private Handler handler;
    private ExecutionListener<B> executionListener;
    private volatile int progress = 0;
    private AtomicBoolean progressPublished = new AtomicBoolean(true);
    private B output;

    public Task() {
        this.handler = new Handler();
        this.executionListener = new ExecutionListener();
    }

    public void setExecutionListener(ExecutionListener executionListener) {
        if(executionListener == null) {
            this.executionListener = new ExecutionListener();
        }
        else {
            this.executionListener = executionListener;
        }
    }

    protected void updateProgress(int progressMade) {
        Log.d("TASK", "Test");
        progress += progressMade;
        if(progressPublished.compareAndSet(true, false)) {
            if(!handler.post(new Runnable() {
                @Override
                public void run() {
                    Log.d("TASK", new Integer(progress).toString() + " - a");
                    executionListener.onProgressUpdate(progress);
                    // Hangs below
                    progressPublished.lazySet(true);
                    Log.d("TASK", new Integer(progress).toString() + " - b");
                }
            })) {
                Log.d("TASK", "Failed to post");
            }
        }
    }

    protected void updateProgress() {
        updateProgress(DEFAULT_PROGRESS_INCREMENT);
    }

    protected abstract B doTask(A input);

    public void execute(final A input, final int priority) {
        EXECUTOR.execute(new Runnable() {
            @Override
            public void run() {
                Thread.currentThread().setPriority(priority);
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        executionListener.onPreExecute();
                    }
                });
                output = doTask(input);
                if(!handler.post(new Runnable() {
                    @Override
                    public void run() {
                        Log.d("TASK", "Done");
                        executionListener.onPostExecute(output);
                    }
                })) {
                    Log.d("TASK", "Failed to post post");
                }
            }
        });
    }

    public void execute(final A input) {
        execute(input, DEFAULT_PRIORITY);
    }
}

ExecutionListener只是一个类来覆盖要在UI上运行的方法,就像AsyncTask的方法一样。代码使用Runnable对象来执行doTask方法,并将更新/结果发送到ExecutionListener中的相应方法。

Thread.currentThread()部分只是为了确保事情在我想要的线程上运行。运行一个经常调用updateProgress()的任务时,问题只会显示出来 - 我已经尝试在onProgressUpdate()方法中使用线程睡眠,这似乎解决了问题,尽管这显然不是一个好的解决方案。

它似乎也只有Log.x / System.out的问题 - 我不知道它们中任何一个的通话频率是否会引起这种问题。我对这个进展功能和记录感到茫然,所以任何建议都会非常感激 - 我也发现这很难解释所以请问你是否需要我澄清一切!

1 个答案:

答案 0 :(得分:0)

结果是Thread.currentThread()。getId()出错了。删除该部分可修复所有问题。在此处跟进问题:Is Java Thread getId() thread-safe?