zoukankan      html  css  js  c++  java
  • 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()中的任务。

  • 相关阅读:
    JSP
    Map集合的四种遍历
    过滤器和监听器
    Web常用对象(2)
    Web常用对象(1)
    Java Web了解和Servlet初次见面
    面向对象之继承(1)
    SpringBoot使用简单缓存
    SpringBoot整合mybatis
    Spring Security 入门学习--数据库认证和授权
  • 原文地址:https://www.cnblogs.com/Peter-Chen/p/6930477.html
Copyright © 2011-2022 走看看