• Android开发--取消AsyncTask


        在Android应用开发过程中,为了防止UI线程堵塞,耗时的工作都应该另起一个后台线程来完成,其中AsyncTask就是其中的一种方式。最近在案子中需要“停止/取消”某个AsyncTask,在网上查了些资料,这里做个笔记。

        查看AsyncTask.java文件,其中有个cancel()函数,可以通过调用cancel(true)来停止正在运行的AsyncTask。

        /**
         * <p>Attempts to cancel execution of this task.  This attempt will
         * fail if the task has already completed, already been cancelled,
         * or could not be cancelled for some other reason. If successful,
         * and this task has not started when <tt>cancel</tt> is called,
         * this task should never run. If the task has already started,
         * then the <tt>mayInterruptIfRunning</tt> parameter determines
         * whether the thread executing this task should be interrupted in
         * an attempt to stop the task.</p>
         * 
         * <p>Calling this method will result in {@link #onCancelled(Object)} being
         * invoked on the UI thread after {@link #doInBackground(Object[])}
         * returns. Calling this method guarantees that {@link #onPostExecute(Object)}
         * is never invoked. After invoking this method, you should check the
         * value returned by {@link #isCancelled()} periodically from
         * {@link #doInBackground(Object[])} to finish the task as early as
         * possible.</p>
         *
         * @param mayInterruptIfRunning <tt>true</tt> if the thread executing this
         *        task should be interrupted; otherwise, in-progress tasks are allowed
         *        to complete.
         *
         * @return <tt>false</tt> if the task could not be cancelled,
         *         typically because it has already completed normally;
         *         <tt>true</tt> otherwise
         *
         * @see #isCancelled()
         * @see #onCancelled(Object)
         */
        public final boolean cancel(boolean mayInterruptIfRunning) {
            mCancelled.set(true);
           

       值得注意的是,调用cancel(true)函数需要注意以下几点:

      1.当AsyncTask已经完成,或则以及被取消,亦或其他原因不能被取消,调用cancel()会失败;

      2.如果AsyncTask还没有开始执行,调用cancel(true)函数后,AsyncTask不会再执行;

      3.如果AsyncTask已经开始执行,参数mayInterruptIfRunning决定是否立即stop该Task;

      4.调用cancel()后,doInBackground()完成后,不再调用onPostExecute(),而是执行onCancelled();

      下面是一个简单的Demo,使用两个Button,分别用来start & stop AsyncTask。

    import android.os.AsyncTask;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    
    public class MainActivity extends AppCompatActivity implements View.OnClickListener{
        private static final String TAG = "AsyncTaskTest";
        private TestTask task = null;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            findViewById(R.id.btn1).setOnClickListener(this);//start async task btn
            findViewById(R.id.btn2).setOnClickListener(this);//stop async task btn
        }
    
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.btn1:
                    task = new TestTask();
                    task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
                    break;
                case R.id.btn2:
                    if (task != null && !task.isCancelled() && task.getStatus() == AsyncTask.Status.RUNNING) {
                        task.cancel(true);
                        task = null;
                    }
                    break;
            }
        }
    
        class TestTask extends AsyncTask<Void, Void, Void> {
    
            @Override
            protected Void doInBackground(Void... params) {
                int count = 5;
                while (count > 0) {
                    count--;
                    if (isCancelled()) {  //通过isCancelled()判断cancel(true)是否成功。
                        Log.d(TAG,"Cancel");
                        break;
                    }
                    Log.d(TAG,"Start Sleep");
                    try {
                        Thread.sleep(2000);//模拟耗时操作
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Log.d(TAG,"End Sleep");
                }
                return null;
            }
    
            @Override
            protected void onPostExecute(Void aVoid) {
                Log.d(TAG,"onPostExecute");
                super.onPostExecute(aVoid);
            }
    
            @Override
            protected void onCancelled() {
                Log.d(TAG,"onCancelled");
                super.onCancelled();
            }
        }
    
    
    }

         当然真实案例中,在doInBackground()函数中,不像Demo中只有一个简单的while()循环,所以可能需要多加几个isCancelled()来结束doInBackground()中的任务。

  • 相关阅读:
    背水一战 Windows 10 (26)
    背水一战 Windows 10 (25)
    背水一战 Windows 10 (24)
    背水一战 Windows 10 (23)
    背水一战 Windows 10 (22)
    背水一战 Windows 10 (21)
    背水一战 Windows 10 (20)
    背水一战 Windows 10 (19)
    背水一战 Windows 10 (18)
    背水一战 Windows 10 (17)
  • 原文地址:https://www.cnblogs.com/Peter-Chen/p/6930477.html
Copyright © 2020-2023  润新知