我所理解的asynctask

Android中有两种十分常见的异步处理消息的机制,一种是Handler机制一种是asynctask机制,Handler机制有其缺点:

(1)代码臃肿

(2)每一个任务都需要开启一个线程

(3)在多任务同时执行的时候不容易对任务进行控制。

其实asynctask是对Handler的封装,这一点我们可以再asynctask的源码中讲到,首先看一下如何简单的使用asynctask。代码如下

public class MyAsyncTask extends AsyncTask<String ,String,String> {
    //在调用execute之后立马被调用
    
private static final String TAG = "MyAsyncTask";
    @Override
    protected void onPreExecute() {
        Log.e(TAG, "onPreExecute: " +Thread.currentThread());
        super.onPreExecute();
    }
    //后台执行的逻辑代码,不能更新UI
    
@Override
    protected String doInBackground(String... params) {
        //执行publishProgress后立马调用onProgressUpdate
        
Log.e(TAG, "doInBackground: " +Thread.currentThread());
        publishProgress("d");
        return null;

    }
    //更新UI
    
@Override
    protected void onProgressUpdate(String... values) {
        Log.e(TAG, "onProgressUpdate: " +Thread.currentThread());
        super.onProgressUpdate(values);
    }
    //返回的结果显示在UI控件上
    
@Override
    protected void onPostExecute(String s) {
        Log.e(TAG, "onPostExecute: " +Thread.currentThread());
        super.onPostExecute(s);
    }
    //在任务中途取消任务,更新UI。

    @Override
    protected void onCancelled() {
        super.onCancelled();
    }

然后就是在MainActivity中我们要实例化一个AsyncTask,代码如下所示。

 

 

MyAsyncTask myAsyncTask =new MyAsyncTask();
myAsyncTask.execute("a");

最后执行结果


可以看到AsyncTask依次执行了onPreExecute()、doInBackground()、onProgressUpData()onPostExecute()。其中只有doInBackground()是在AsyncTask线程中执行的其他均在UI线程中执行。那么他们之间是如何相互调用的呢?

首先我们从mainactivity中的execute进入AsyncTask看一看。在AsyncTask中首先调用了executeOnExecutor()方法。

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;
}

在该方法中首先判断了当前AsyncTask的状态,AsyncTask有三种状态,这三种状态在AsyncTask的内部内Status中有体现三种状态分别为PENDING

RUNNINGFINISHEDAsyncTask的状态为RUNNING,和FINISHED的时候抛出异常,由此可知Asynctask每一次实例化只能被执行一次,如果多次执行会抛出异常。当Asynctask的状态是PENDING的时候,会首先将状态更改为RUNNING,接着重点来了我们上面说到执行execute的时候会立马执行onPreExecute(),但是我们发现没有接着执行doInBackground()方法啊,不要急我们接着看mWorker,最后发现mWorker,是一个WorkerRunnable类型的,他重写了call()方法。

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;
}

call()中我们看到了doInBackground()在这里被调用了。当我们在doInBackground()中调用publishProgress("d")的时候

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

可以看到Handler发送了一个消息,这也解释了为什么说Asynctask是对Handler的封装,这个Handler是InternalHandler中定义的

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;
    }
}

在这个时候我们发送的是MESSAGE_POST_PROGRESS:消息,在这里Asynctask执行了onProgressUpDate(),当任务执行完毕的时候发送MESSAGE_POST_RESULT这时候执行finish()将数据发送给onPostExecute(),任务结束。

当然虽说AsynctaskHandler进行了很好的封装但是其任然有很多缺点例如:

(1)很多人以为Asynctask会在Activity销毁的时候同时销毁,实际上Asynctaskactivity销毁的时候有可能不会被销毁,会一直执行到DoInBackground()执行完毕才会被销毁,同时如果Activity被销毁也有可能造成Asynctask的崩溃,有可能Asynctask操作的View已经被回收造成Asynctask异常。

(2)Asynctaskactivity的非静态内部类中定义的时候会持有当前activity的引用,即使我们销毁了当前Activity但是Asynctask仍然会在后台运行,此时当前Activity无法被回收造成内存泄漏。

(3)Asynctask还有可能会丢失运行的结果,例如屏幕旋转或者后台的activity重新被创建,那么Asynctask持有的是之前的Activity的引用,这时调用onPostExecute更新界面将没有作用。

以上就是我对Asynctask的理解了如有理解错误之处还望批评指正。

猜你喜欢

转载自blog.csdn.net/u014379448/article/details/52708381