android 多线程学习5:AsyncTask

android 多线程学习1:一些基础
android 多线程学习2:线程的创建与方法分析
android 多线程学习3:synchronized与volatile与线程安全对象
android 多线程学习4:线程池ThreadPoolExecutor
android 多线程学习5:AsyncTask
android 多线程学习6:HandlerThread
android 多线程学习7:Handler消息处理机制


AsyncTask使用

直接使用AsyncTask有内存泄漏的风险 (类似于Handler的内存泄漏问题android Handler内存泄漏的分析与解决)

android studio 提示

因此,使用AsyncTask还是推荐静态内部类继承使用。

AsyncTask方法说明:

    /**
     * 静态内部类避免内存泄漏
     *
     * Params:用于设置execute和doInBackground方法的参数的数据类型。
     * Progress:用于设置onProgressUpdate和publishProgress方法的参数的数据类型。
     * Result:用于设置onPostExecute方法的参数的数据类型和doInBackground方法的返回值类型。
     */
    private static class MyTask extends AsyncTask {

        /**
         * 弱引用外部类
         */
        private final WeakReference mTarget;

        public MyTask(TestActivity target) {
            mTarget = new WeakReference<>(target);
        }

        /**
         * 在工作线程执行,首先被调用,执行初始化操作
         */
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        /**
         * 在工作线程执行,后台执行耗时的操作
         */
        @Override
        protected Float doInBackground(String... strings) {
            /**
             * publishProgress方法向主线程中的Handler发送消息,Handler接到消息后会调用onProgressUpdate方法
             */
            publishProgress(0, 50 ,100);
            return null;
        }

        /**
         * 在主线程执行,处理执行结果
         *
         * 当doInBackground方法执行完毕后,onPostExecute方法将被调用。
         * onPostExecute方法的参数就是doInBackground方法的返回值。
         *
         * 若doInBackground方法中途被终止,则同样会调用onPostExecute方法
         */
        @Override
        protected void onPostExecute(Float aFloat) {
            super.onPostExecute(aFloat);
        }

        /**
         * 在主线程执行, 显示线程任务执行的进度
         */
        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
        }

        /**
         * 在主线程执行,在cancel(boolean mayInterruptIfRunning)被调用或任务完成之后
         */
        @Override
        protected void onCancelled() {
            super.onCancelled();
        }
    }

使用:

        for (int i = 0; i < 10; i++) {
            //顺序执行
            new MyTask(this).execute("参数1", "参数2");
            //并发执行(当多任务访问同一个资源的时,会出现并发问题)
            new MyTask(this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "参数1", "参数2");
        }

AsyncTask的注意事项

1. AsyncTask实例必须在ui线程创建么?

首先看看AsyncTask的构造方法是怎样的:


AsyncTask构造方法

AsyncTask构建Handler

由以上代码可见,getMainHandler()会调用new InternalHandler(Looper.getMainLooper())方法,这里传入了主线程的Looper对象,即无论我们在哪个线程创建AsyncTask实例,AsyncTask中的Handler都是用主线程的Looper来实例化的。

所以:
1. 可以在子线程中调用AsyncTask()构造器方法创建AsyncTask实例。
即使子线程中没有调用Looper.prepare()方法创建Looper对象,且AsyncTask也不支持传子线程的Looper对象来构造Handler,不过它提供了带Looper参数的构造方法,只是暂时是@hide(对开发者隐藏)
2. 在哪个线程创建的AsyncTask实例,onPreExecute和onPostExecute方法还是会运行在那个线程中。
虽然AsyncTask中的Handler还是用主线程中的Looper对象来实例化的,但是Handler的创建是在非UI线程。所以,可以在子线程实例AsyncTask,却不能在onPreExecute和onPostExecute方法中更新UI操作。

2. AsyncTask只能执行一次

AsyncTask内部有一个枚举类型的Status用于维护执行状态:PENDING、RUNNING、FINISHED。默认情况下是PENDING,表示可以执行,当调用execute方法之后,会检查其状态是否是PENDING,如果不是的话就会抛出异常。


AsyncTask状态
3.不能在AsyncTask之外直接调用doInBackground、onPreExecute、onPostExecute 、onProgressUpdate ,这几个方法是有AsyncTask对象自己内部回调的。
4. boolean cancel(boolean mayInterruptIfRunning) 能中断AsyncTask吗?

答案:不能。
cancel(true)方法仅仅是将AsyncTask的cancel标识符设置为true,仍然需要去手动判断isCancelled()来停止。如:

        @Override
        protected Float doInBackground(String... strings) {
            if(isCancelled()) {
                return null;
            }
            //do something
            return 888.88F;
        }

        @Override
        protected void onPostExecute(Float aFloat) {
            if(isCancelled()) {
                return;
            }
            //do something
        }



(部分内容参考于网络,如有不妥,请联系删除~)

你可能感兴趣的:(android 多线程学习5:AsyncTask)