android中异步消息的处理机制

一:问题提出

在android中是不允许我们在子线程中去进行UI的更新,但是有时候我们有不得不根据实际的情况去在子线程中去执行一些耗时的任务(如网络请求,下载等),然后在根据任务返回的结果进行UI控件的更新。在不知道android的异步消息处理机制时,这对我们来说是一个非常棘手的问题。

对于这种情况,android系统为我们提供了一套异步消息的处理机制,通过运用这套机制,就能解决上述的问题。下面我们来进行学习。

二:Thread

一:Handler异步消息处理机制

1、异步消息处理机制主要由四个组成部分:Looper、Handler、Message、MessageQueue。
异步消息处理线程启动后,会进入一个无限的循环体中,每循环一次,从循环体内部的消息队列(MessageQueue)取出一个消息,然后进行消息的处理。处理完毕后,继续循环。如果消息队列中没有消息,则会进行阻塞等待。
下面一次梳理整个过程中的四个组成部分以及其功能:

2、Message
既然是是异步的消息处理,肯定会涉及到其他线程和主线程之间的通信,Message就是这个通信大使吧,负责在其他的线程中向主线程传递消息。在传递消息的过程,Message会携带一些消息,比如要更新主线程中的一个文本框,则Message.what = UPDATE_TEXT;

//创建一个message对象,携带消息后,//利用handler的sendmessage方法发送出去Message message = new Message();Message.what = = UPDATE_EDITTEXT;handler.sendMessage(message);

3、Handler(消息处理者)
Handler主要用于处理消息或者发送消息
sendMessage()—发送消息
handlMessage()—处理消息,接受到其他线程传来的消息(what)后进行处理

//在主线程中创建Handler实例private Handler handler = new Handler(){    public void handlerMessage(Message msg){        switch(msg.what){            case UPDATE_EDITTEXT:                //进行UI的更新                editText.setText("new text");                break;            default:                break;        }    }};

4、MessageQueue(消息队列)
它用了存放所有通过Handler发送的消息,每一个线程都只有一个MessageQueue。

5、Looper(消息队列的管理者)
作为MessageQueue的管理者,其与当前的线程绑定,保证了一个线程只有一个Looper实例,只管理一个MessageQueue。

Looper.prepare()方法只能被调用一次,它用于创建一个MessageQueue,同时保证了一个线程中只有一个Looper实例。

通过loop()方法,不断的从MessageQueue中取出消息,没有消息则阻塞,然后交给handlerMessage()处理。

6、最后附一张草图来总结一下:

二:view的post()和postDelayed方法

例如:每5秒更新一次UI

if(count%5==0){    tv.post(new Runnable(){        public void run(){            tv.setText(count+"%完成!");        }    });}

二:Activity的runOnUiThread()方法

当程序处于一个Thread类中时,可以利用runOnUiThread()返回主线程进行更新UI。

runOnUiThread(new Runnable() {    @Override    public void run() {     //关闭进度条     closeProgressDialog();               Toast.makeText(ChooseAreaActivity.this, "加载失 败",Toast.LENGTH_SHORT).show();    }});

三:AsyncTask

通过上述的异步消息处理机制,我们已经能够在子线程中解决更新UI控件的问题了。但是在上面,我们需要在程序中手动开启一个Thread,然后再run()方法中实现相应的逻辑。
其实android还给我们提供另一个方法,那就是AsyncTask,AsyncTask是将异步消息处理机制封装起来,借助这个类,我们就可以很简单的从子线程切换到主线程。下面直接通过一个例子来说明AsyncTask的使用

/** *AsyncTask是一个抽象类,共有三个参数: * 1.Params:在执行AsyncTask时需要传入的泛型参数,用于在后台任务中使 用,我们这里传入的是Void * 2.Progress:后台任务执行时,徐娅用到的泛型参数 * 3.Result:后台任务处理完成后,如果需要返回一个值,则可以设置为泛型参数 * 注意:这里几个参数的类型直接涉及到下面一些函数的参数列表中的函数类型 */class MyAsyncTask extends AsyncTask<Void,Interger,Boolean>{    /** *onpreExecute():在任务执行之前调用,主要用于界面上的一些初始化 *操作 */    protected void onpreExecute(){        //开启一个进度条        progressDailog.show();    }    /** *在这个函数中处理主要的耗时操作,但是不能再这里进行UI的更新 */    protected Boolean doInBackground(Void...params){        while(true){            //模拟一个下载更新            int down= down();            //调用publishProgess反馈下载进度            publishProgess(down);            if(down>=100){                break;            }        }    /** *在这里对界面上的UI进行更新 */    protected void onProgressUpdate(Integer...values){        //在这里进行下载进度的更新        progressDailog.setMessage("当前下载进度 为:"+values[0]+"%");//这里的values[0]就是publishProgess()传来的down    }    /** *根据任务结束后返回的值来对UI进行一些操作, *在这里关闭*progressDailog */    onPostExecute(Boolean Result){        progressDailog.dismiss();    }}

四:总结常用的异步处理

1、所有过长或复杂的计算获操作
2、请求获取长度不定的数据集
3、解析数据集
4、处理多媒体文件,例如图像、视频或音频
5、对长度不定的数据结构进行迭代
6、获取网络资源
7、获取地理位置服务
8、获取内容提供器接口
9、接入本地数据库,本地文件

最后:

欢迎大家关注我的博客,我基本上会一周更新一篇博客,来记录我的所学所想。作为一个新人,才开始写作博客,欢迎各位指出我文章中的错误以及不足之处,与我多多交流。

更多相关文章

  1. Android(安卓)NFC近场通信02----读写卡的准备工作
  2. Android音视频处理技术 视频录制
  3. Android(安卓)BroadcastReceiver(广播)实现消息发送
  4. android 使用handler更新ui,使用与原理分析详解(附上代码以及截图)
  5. Android(安卓)之 Window、WindowManager 与窗口管理
  6. Android中AsyncTask的简单用法
  7. android UncaughtExceptionHandler全局异常处理
  8. 硬核干货!系统盘点Android开发者必须掌握的Java知识体系,收藏这一
  9. Android的内存泄漏和调试

随机推荐

  1. Mac mini M1上成功启动Ubuntu
  2. CentOS联合创始人成立公司赞助Rocky Linu
  3. Objective-C 之父去世,他推动了苹果软件生
  4. 谷歌开发MicroDroid,用于虚拟机的精简版An
  5. 如何使用Movavi Video Editor Plus创建画
  6. 一个工作3年运维自我介绍话术 offer到碗
  7. 新增命令
  8. SSD可靠性影响因素、原理和解决方法
  9. BSD系统正在死亡?一些安全研究人员这样认
  10. 闪存(SSD)技术,MLC和SLC差距到底有多大?