• AsyncTask、HandlerThread、IntentService和线程池


    AsyncTask

      AsyncTask 是一种轻量级的异步任务类,可以在线程池中执行后台任务,然后把执行的进度和最终结果传递给主线程用于更新UI。

    可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程.

      AsyncTask 并不合适进行特别耗时的后台任务,对于特别耗时的任务来说,建议使用线程池。

    AsyncTask 和 Handler对比:

    1 )  Async使用的优点:

      l  简单,快捷

      II 过程可控      

    使用的缺点:

      l  在使用多个异步操作和并需要进行Ui变更时,就变得复杂起来.

    2 )Handler异步实现的原理和适用的优缺点

      在Handler 异步实现时,涉及到 Handler, Looper, Message,Thread四个对象,实现异步的流程是主线程启动Thread(子线程)àthread(子线程)

    运行并生成Message-àLooper获取Message并传递给HandleràHandler逐个获取Looper中的Message,并进行UI变更。

      使用的优点:

      l  结构清晰,功能定义明确

      lI  对于多个后台任务时,简单,清晰

       

    使用的缺点:

      l  在单个后台异步处理时,显得代码过多,结构过于复杂(相对性)

    Android 的AsyncTask比Handler更轻量级一些,适用于简单的异步处理。

    AsyncTask定义了三种泛型类型 Params,Progress和Result。

    • Params 启动任务执行的输入参数,比如HTTP请求的URL。
    • Progress 后台任务执行的百分比。
    • Result 后台执行任务最终返回的结果,比如String。

    使用过AsyncTask 的同学都知道一个异步加载数据最少要重写以下这两个方法:

    • doInBackground(Params…) 后台执行,比较耗时的操作都可以放在这里。注意这里不能直接操作UI。此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间。在执行过程中可以调用publicProgress(Progress…)来更新任务的进度。
    • onPostExecute(Result)  相当于Handler 处理UI的方式,在这里面可以使用在doInBackground 得到的结果处理操作UI。 此方法在主线程执行,任务执行的结果作为此方法的参数返回

    有必要的话你还得重写以下这三个方法,但不是必须的:

    • onProgressUpdate(Progress…)   可以使用进度条增加用户体验度。 此方法在主线程执行,用于显示任务执行的进度。
    • onPreExecute()        这里是最终用户调用Excute时的接口,当任务执行之前开始调用此方法,可以在这里显示进度对话框。
    • onCancelled()             用户调用取消时,要做的操作

    使用AsyncTask类,以下是几条必须遵守的准则:

    • Task的实例必须在UI thread中创建;
    • execute方法必须在UI thread中调用;
    • 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法;
    • 该task只能被执行一次,否则多次调用时将会出现异常;

    HandlerThread

      HandlerThread 其实是一种Thread,它是可以使用Handler的THread,它的实现其实很简单就是在run方法中通过Looper.prepare()来创建消息队列,并通过Looper.loop来开启消息循环,这样在实际的使用

    中就允许在HandlerThread中创建Handler了。

    private void init4(){
            //创建一个线程,线程名字:handler-thread
            myHandlerThread = new HandlerThread( "handler-thread") ;
            //开启一个线程
            myHandlerThread.start();
            //在这个线程中创建一个handler对象
            Log.d(TAG, "init4: "+Thread.currentThread().getId());
            handler3 = new Handler( myHandlerThread.getLooper() ){
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    //这个方法是运行在 handler-thread 线程中的 ,可以执行耗时操作
                    Log.d(TAG , "消息: " + msg.what + "  线程: " + Thread.currentThread().getId()  ) ;
                }
            };
    
            //在主线程给handler发送消息
            handler3.sendEmptyMessage( 1 ) ;
    
            new Thread(new Runnable() {
                @Override
                public void run() {
                    Log.d(TAG, "new runnable "+Thread.currentThread().getId());
                    //在子线程给handler发送数据
                    handler3.sendEmptyMessage( 2 ) ;
                }
            }).start() ;
        }
    View Code

    •  在上述代码中,通过HandlerThread开启一个新的线程,将主线程中的Loop转到子线程中处理,降低了主线程的压力,

    使主界面更流畅。  它有自己的MessageQueue不会干涉主线程中的消息队列。

    •    程序中如果将此HandlerThread注释掉,程序会出错,因为它会在主线程中发消息给主线程去处理。
    •  在HandlerThread内部消息,处理任务是串行执行,消息是顺序到达的。当队列中某个任务执行时间较长时,后续的任务就会被延迟处理。

    利用HandlerThread将Runnable运行在子线程的工具类

    public class BackTaskRunner {
        private static final String TAG = "BackTaskRunner";
        private HandlerThread handlerThread;
        private Handler handler;
    
        private BackTaskRunner() {
            handlerThread = new HandlerThread(TAG);
            handlerThread.start();
            handler = new Handler(handlerThread.getLooper());
        }
    
        public static Handler getHandler() {
            return SingletonHolder.sRunner.handler;
        }
    
        private static class SingletonHolder {
            static BackTaskRunner sRunner = new BackTaskRunner();
        }
    }

    将代码运行在子线程:

    BackTaskRunner.getHandler().post(new Runnable() {
                @Override
                public void run() {
                    //需要运行的代码
                }
            });
    
  • 相关阅读:
    PHP 高精度计算
    PHPWord使用方法
    羽毛球
    大数据(2)
    大数据(1)
    Centos 7 启动错误:XFS_WANT_CORRUPTED_GOTO 修复
    selenium 自动化工具
    python 开发技巧(0)-- 各个系统的python安装
    Yii简单使用阿里云短信教程!
    VMware虚拟机 Ubuntu 实用技巧 (2)桥接模式连接网络与网卡的配置
  • 原文地址:https://www.cnblogs.com/NeilZhang/p/7450185.html
Copyright © 2020-2023  润新知