Android学习笔记十:异步处理

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android学习笔记十:异步处理相关的知识,希望对你有一定的参考价值。

转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/7520700.html

 

    一:基础概念

    UI线程:当android程序第一次启动时,Android会同时启动一条主线程(Main Thread),主线程主要负责处理与UI相关的事件,如用户的按键事件、屏幕绘图事件,并把相关的事件分发到对应的组件进行处理。主线程通常又被称为UI线程,Android只允许UI线程修改Activity里的UI组件。

    子线程:在程序的activity中创建、启动的线程为子线程,子线程中不能操作UI组件。

    后台任务:后台任务一般用子线程来完成,通常用于执行一些耗时任务如:复杂计算、下载文件等。因为这些操作是与UI线程同时运作的,所以又称为异步操作。

 

    二:异步方式之——消息传递机制

    我们知道,只有UI线程才能修改、操作界面组件,那么其他子线程中的信息如何反映到UI中呢?那就需要子线程把信息汇总到UI线程,由UI线程显示到组件上。

    这个过程,就是消息传递机制。

    1)消息传递机制原理图

    技术分享

    2)消息传递机制解释

    首先,UI线程中维护一个消息队列MessageQueue、一个循环者Looper、一个处理者Handler:消息队列负责接受、存储其他子线程发送过来的消息,等待UI线程处理;循环者不停地轮询消息队列,每次都提取队首一个消息;处理者负责处理Looper提取出来的消息,并负责把结果在UI进行呈现。其中,MessageQueue和Looper随着UI线程启动而自动创建并运行,Handler则需要手动定义

    其次,在UI线程中创建并启动子线程,子线程中通过同一个handler(通常这个handler为acticity代码中的全局变量,因此子线程中可见)来发送消息,从而把消息发送到了当前UI线程的handler对应的消息队列中。

    3)实现步骤

    根据消息传递机制的原理,我们只需针对实现各个环节需要的东西即可。

    首先:定义、创建Handler,重写其中的handlerMessage方法,处理消息

private Handler mHandler = new Handler() {  
        @Override  
        public void handleMessage(Message msg) {  
            switch (msg.what) {  
                //根据消息内容,作处理
            }  
        }  
    };  

    然后:定义子线程,在其中定义发送消息语句

 Runnable runnable = new Runnable() {  
        @Override  
        public void run() {  
            Message message = new Message();  
            message.what = 消息标签;  
            mHandler.sendMessage(message);  //handler是UI线程中的handler
        }  
    };  

    最后:根据条件,创建子线程实例并启动

mThread = new Thread(runnable);  
mThread.start();  

    4)应用场景

    Handler机制适合多个子线程存在的情况,这样可以把多个子线程发送过来的信息在UI线程中统一处理、绘制呈现。

   【附:如果需要在子线程中使用handler和looper,则需要获取到UI线程中的handler、looper对象。具体方法见:http://blog.csdn.net/logicteamleader/article/details/46591499

 

    三:单个异步任务——AsyncTask

    消息传递机制看起来比较复杂,涉及到了消息队列的应用,这几乎是大型Web应用的架构层面才会用到的模式了。

    如果只是单个的异步任务,用消息传递机制就有些过于麻烦了,为此,Android为我们提供了一个辅助类——AsyncTask。

    AsyncTask类,可以理解为异步任务执行者;这个类的设计目的很明确,就是为了“执行一个较为耗时的异步任务(最多几秒钟),然后更新界面”。

 

    1:使用AsyncTask

    1)继承AsyncTask,定义子类,重写其中的几个方法:

     AsyncTask需要重写5个方法,分别是:

    1、onPreExecute方法:准备运行,该回调函数在任务被执行之后立即由UI线程调用,一般可以显示进度条。

    2、doInBackground(Params ...)方法:正在后台运行,通常在这里执行耗时的后台计算,计算结果返回给函数,这里如果AsyncTask的第三个参数是Void的话不需要返回,这里不能更新UI,但是可以调用publishProgress(Progress ...)方法完成。

    3、onProgressUpdate(Progress ...)方法:进度更新,UI线程在publishProgress(Progress ...)方法调用完成后被调用,一般动态显示一个进度。

    4、onPostExecute(Result)方法:完成后台任务,会返回,这里可以进行些UI的操作,比如提醒任务执行的结果,以及关闭掉进度条对话框等。

    5、onCancelled方法:取消任务,在调用AsyncTask的cancel()方法的时候调用。

class ViewContentTask extends AsyncTask<Void, Integer, Boolean> {//三个范型分别对应下面doInBackground、onProgressUpdate、onPostExecute三个方法的参数类型
        @Override  
        protected Boolean doInBackground(Void... voids) {  
            return null;  
        }  
  
        @Override  
        protected void onProgressUpdate(Integer... values) {  
        }  
  
        @Override  
        protected void onPostExecute(Boolean b) {  
            //操作UI组件  
        }  
  
        @Override  
        protected void onPreExecute() {  
        }  
  
        @Override  
        protected void onCancelled() {  
        }  
    }  
  

    2)创建异步任务实例,启动异步任务

ViewContentTask  task = new ViewContentTask();  
task.execute();  

 

    2:AsyncTask工作原理

    当一个异步任务被执行时,要经历四步: 
    onPreExecute(),在UI线程中执行,它会在异步任务开始前执行,一般用来设置任务参数; 
    doInBackground, 最重要的方法,在子线程中执行(事实上,只有它在子线程中执行,其他方法都在UI线程中执行)。当onPreExecute结束后,本方法立刻执行,它用   来进行后台的耗时计算,异步任务的参数会被传给它,执行完成的结果会被送给第四步;执行途中,它还可以调用publishProgress 方法来通知UI线程当前执行的进度; 
    onProgressUpdate, 当publishProgress 被调用后,它在UI线程中执行,刷新任务进度,一般用来刷新进度条等UI部件; 
    onPostExecute, 当后台的异步任务完成后,它会在UI线程中被调用,并获取异步任务执行完成的结果。

    

 





以上是关于Android学习笔记十:异步处理的主要内容,如果未能解决你的问题,请参考以下文章

Android学习笔记 十六 使用RxBinding响应控件的异步事件

android 学习随笔十二(网络:使用异步HttpClient框架)

ANDROID_MARS学习笔记_S04_002_用AsyncTask实现异步操作

Java基础学习笔记十八 异常处理

Android异步载入学习笔记之四:利用缓存优化网络载入图片及ListView载入优化

Android学习笔记进阶十三获得本地全部照片