Android AsyncTask类

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chennai1101/article/details/83957301

相关文章
Android AsyncTask类
Android Handler类

1. AsyncTask类

AsyncTask,异步任务,用于在后台线程运行一个任务,在UI线程上修改界面。AsyncTask<Params, Progress, Result>需要确认三个泛型类型,如果类型不被使用,使用Void类型。

  • Params,启动任务执行的输入参数
  • Progress,后台任务执行的百分比
  • Result,后台运行结果

例如需要下载一个图片并显示在ImageView上,指定Params为图片地址,Progress以数值代替,Result返回一个Bitmap对象。

private class BitmapAsyncTask extends AsyncTask<String, Integer, Bitmap> {

    @Override
    protected Bitmap doInBackground(String... strings) {
        try {
            URL uri = new URL(url);
            URLConnection connection = uri.openConnection();
            InputStream input = connection.getInputStream();
            int size = connection.getContentLength();

            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

            byte[] buffer = new byte[1024];
            int length, sum = 0;

            while ((length = input.read(buffer)) != -1) {
                outputStream.write(buffer, 0, length);
                sum += length;
                publishProgress(sum * 100 / size);
            }
            input.close();

            return BitmapFactory.decodeByteArray(outputStream.toByteArray(), 0, outputStream.size());
        } catch (IOException e) {
        }

        return null;
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        mPb.setProgress(values[0]);
    }

    @Override
    protected void onPostExecute(Bitmap bitmap) {
        mIvBitmap.setImageBitmap(bitmap);
    }
}

BitmapAsyncTask继承AsyncTask类,且至少覆盖doInBackground方法

  • onPreExecute(),在UI线程上调用,在运行后台线程前调用
  • doInBackground(Params… params),在后台运行工作线程
  • onProgressUpdate(Progress… values),调用publishProgress方法修改进度
  • publishProgress(Progress… values),在UI线程调用该方法改变进度
  • onPostExecute(Result result),工作线程运行完毕,在UI线程上修改界面

调用execute方法下载

new BitmapAsyncTask().execute(url);

效果如下
在这里插入图片描述

2. AsyncTask类解析

AsyncTask构造方法,分别定义了mHandlermWorkermFuture

public AsyncTask() {
    this((Looper) null);
}

public AsyncTask(@Nullable Looper callbackLooper) {
    mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
        ? getMainHandler()
        : new Handler(callbackLooper);

    mWorker = new WorkerRunnable<Params, Result>() {
        public Result call() throws Exception {
            mTaskInvoked.set(true);
            Result result = null;
            try {
                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                //noinspection unchecked
                result = doInBackground(mParams);
                Binder.flushPendingCommands();
            } catch (Throwable tr) {
                mCancelled.set(true);
                throw tr;
            } finally {
                postResult(result);
            }
            return result;
        }
    };

    mFuture = new FutureTask<Result>(mWorker) {
        @Override
        protected void done() {
            try {
                postResultIfNotInvoked(get());
            } catch (InterruptedException e) {
                android.util.Log.w(LOG_TAG, e);
            } catch (ExecutionException e) {
                throw new RuntimeException("An error occurred while executing doInBackground()",
                        e.getCause());
            } catch (CancellationException e) {
                postResultIfNotInvoked(null);
            }
        }
    };
}

mHandler是一个Handler类,处理MESSAGE_POST_RESULTMESSAGE_POST_PROGRESS两个事件,在主线程中调用AsyncTask的finishonProgressUpdate方法。

private static Handler getMainHandler() {
    synchronized (AsyncTask.class) {
        if (sHandler == null) {
            sHandler = new InternalHandler(Looper.getMainLooper());
        }
        return sHandler;
    }
}

private static class InternalHandler extends Handler {
    public InternalHandler(Looper looper) {
        super(looper);
    }

    @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
    @Override
    public void handleMessage(Message msg) {
        AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
        switch (msg.what) {
            case MESSAGE_POST_RESULT:
                // There is only one result
                result.mTask.finish(result.mData[0]);
                break;
            case MESSAGE_POST_PROGRESS:
                result.mTask.onProgressUpdate(result.mData);
                break;
        }
    }
}

执行AsyncTask的execute方法,会先调用onPreExecute方法,配置mWorkermParams属性,最后调用Executorexecute方法,mFuture会调用mWorkcall方法和自身的done方法。call方法调用doInBackground,而done方法调用postResult

public final AsyncTask<Params, Progress, Result> execute(Params... params) {
    return executeOnExecutor(sDefaultExecutor, params);
}

public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
        Params... params) {
    if (mStatus != Status.PENDING) {
        switch (mStatus) {
            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)");
        }
    }

    mStatus = Status.RUNNING;

    onPreExecute();

    mWorker.mParams = params;
    exec.execute(mFuture);

    return this;
}

private Result postResult(Result result) {
    @SuppressWarnings("unchecked")
    Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
            new AsyncTaskResult<Result>(this, result));
    message.sendToTarget();
    return result;
}

AsyncTask的publishProgress方法,在UI线程里修改进度。

protected final void publishProgress(Progress... values) {
    if (!isCancelled()) {
        getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
                new AsyncTaskResult<Progress>(this, values)).sendToTarget();
    }
}

3. 总结

  • AsyncTask必须在UI线程中被调用。
  • doInBackground方法会被自动调用,并在后台线程中运行。
  • onPreExecuteonPostExecuteonProgressUpdate会在UI线程中被调用。
  • doInBackground的返回值会传给onPostExecute

猜你喜欢

转载自blog.csdn.net/chennai1101/article/details/83957301