您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 人事档案/员工关系 > android多线程处理
第十六章Android多线程目标Android进程理解Android多线程概念Handler、Message、MessageQueueLooper同线程内不同组件间的消息传递子线程传递消息给主线程AsyncTaskAndroid进程在了解Android线程之前得先了解一下Android的进程。当一个程序第一次启动的时候,Android会启动一个LINUX进程和一个主线程。默认的情况下,所有该程序的组件都将在该进程和线程中运行。同时,Android会为每个应用程序分配一个单独的LINUX用户。Android会尽量保留一个正在运行进程,只在内存资源出现不足时,Android会尝试停止一些进程从而释放足够的资源给其他新的进程使用,也能保证用户正在访问的当前进程有足够的资源去及时地响应用户的事件。Android会根据进程中运行的组件类别以及组件的状态来判断该进程的重要性,Android会首先停止那些不重要的进程。按照重要性从高到低一共有五个级别:五个级别前台进程前台进程是用户当前正在使用的进程。只有一些前台进程可以在任何时候都存在。他们是最后一个被结束的,当内存低到根本连他们都不能运行的时候,在这种情况下,设备会进行内存调度,中止一些前台进程来保持对用户交互的响应。可见进程可见进程不包含前台的组件但是会在屏幕上显示一个可见的进程是的重要程度很高,除非前台进程需要获取它的资源,不然不会被中止。服务进程运行着一个通过startService()方法启动的service,这个service不属于上面提到的2种更高重要性的。service所在的进程虽然对用户不是直接可见的,但是他们执行了用户非常关注的任务(如播放mp3,从网络下载数据)。只要前台进程和可见进程有足够的内存,系统不会回收他们。后台进程运行着一个对用户不可见的activity(调用过onStop()方法).这些进程对用户体验没有直接的影响,可以在服务进程、可见进程、前台进程需要内存的时候回收。通常,系统中会有很多不可见进程在运行,他们被保存在LRU(leastrecentlyused)列表中,以便内存不足的时候被第一时间回收。如果一个activity正确的执行它的生命周期,关闭这个进程对于用户体验没有太大的影响。空进程未运行任何程序组件。运行这些进程的唯一原因是作为一个缓存,缩短下次程序需要重新使用的启动时间。系统经常中止这些进程,这样可以调节程序缓存和系统缓存的平衡。单线程模型单线程模型当一个程序第一次启动时,Android会同时启动一个对应的主线程(MainThread),主线程主要负责处理与UI相关的事件,如用户的按键事件,用户接触屏幕的事件以及屏幕绘图事件,并把相关的事件分发到对应的组件进行处理。所以主线程通常又被叫做UI线程。在开发Android应用时必须遵守单线程模型的原则:AndroidUI操作并不是线程安全的并且这些操作必须在UI线程中执行。子线程更新UIAndroid的UI是单线程(Single-threaded)的。为了避免拖住GUI,一些较费时的对象应该交给独立的线程去执行。如果幕后的线程来执行UI对象,Android就会发出错误讯息CalledFromWrongThreadException。以后遇到这样的异常抛出时就要知道怎么回事了!主线程与子线程我们创建的Service、Activity以及Broadcast均是一个主线程处理,这里我们可以理解为UI线程。但是在操作一些耗时操作时,比如I/O读写的大文件读写,数据库操作以及网络下载需要很长时间,为了不阻塞用户界面,出现ANR的响应提示窗口,这个时候我们可以考虑使用Thread线程来解决.对于从事过J2ME开发的程序员来说Thread比较简单,直接匿名创建重写run方法,调用start方法执行即可。或者从Runnable接口继承,但对于Android平台来说UI控件都没有设计成为线程安全类型,所以需要引入一些同步的机制来使其刷新,这点Google在设计Android时参考了下Win32的消息处理机制。子线程操作在Android中,只要是关于UI相关的东西,就不能放在子线程中,因为子线程是不能操作UI的,只能进行数据、系统等其他非UI的操作。在单线程模型下,为了解决类似的问题,Android设计了一个MessageQueue(消息队列),线程间可以通过该MessageQueue并结合Handler和Looper组件进行信息交换。下面将对它们进行分别介绍andriod提供了Handler和Looper来满足线程间的通信。例如一个子线程从网络上下载了一副图片,当它下载完成后会发送消息给主线程,这个消息是通过绑定在主线程的Handler来传递的。MessageMessage消息,线程间交流的信息,处理数据后台线程需要更新UI,则发送Message内含一些数据给UI线程。publicfinalclassMessageimplementsParcelable{publicintwhat;publicMessengerreplyTo;longwhen;Bundledata;Handlertarget;Runnablecallback;Messagenext;privatestaticObjectmPoolSync=newObject();privatestaticMessagemPool;privatestaticintmPoolSize=0;privatestaticfinalintMAX_POOL_SIZE=10;When:向Handler发送Message生成的时间Data:在Bundler对象上绑定要线程中传递的数据Next:当前Message对一下个Message的引用Handler:处理当前Message的Handler对象.mPool:通过字面理解可能叫他Message池,但是通过分析应该叫有下一个Message引用的Message链更加适合.其中Message.obtain(),通过源码分析就是获取断掉Message链关系的第一个Message.HandlerHandler承担着接受子线程传过来的(子线程用sedMessage()或sendEmptyMessage方法传弟)Message对象(里面包含数据),把这些消息放入主线程队列中,配合主线程进行更新UI使用Handler,需要implement该类的handleMessage(Message)方法,它是处理这些Message的操作内容,例如UpdateUI。通常需要子类化Handler来实现handleMessage方法。Handler可以分发Message对象和Runnable对象到主线程中,每个Handler实例,都会绑定到创建他的线程中(一般是位于主线程),它有两个作用:安排消息或Runnable在某个主线程中某个地方执行,安排一个动作在不同的线程中执行MessageQueueMessageQueue消息队列,用来存放通过Handler发布的消息,按照先进先出执行。每个messagequeue都会有一个对应的Handler。Handler会向messagequeue通过两种方法发送消息:sendMessage或post。这两种消息都会插在messagequeue队尾并按先进先出执行。但通过这两种方法发送的消息执行的方式略有不同:通过sendMessage发送的是一个message对象,会被Handler的handleMessage()函数处理;而通过post方法发送的是一个runnable对象,则会自己执行。LooperLooper是每条线程里的MessageQueue的管家。Android没有Global的MessageQueue,而Android会自动替主线程(UI线程)建立MessageQueue,但在子线程里并没有建立MessageQueue。所以调用Looper.getMainLooper()得到的主线程的Looper不为NULL,但调用Looper.myLooper()得到当前线程的Looper就有可能为NULL。对于子线程使用Looper,APIDoc提供了正确的使用方法:classLooperThreadextendsThread{publicHandlermHandler;publicvoidrun(){Looper.prepare();//创建本线程的Looper并创建一个MessageQueuemHandler=newHandler(){publicvoidhandleMessage(Messagemsg){//processincomingmessageshere}};Looper.loop();//开始运行Looper,监听MessageQueue}}Message机制的大概流程在Looper.loop()方法运行开始后,循环地按照接收顺序取出MessageQueue里面的非NULL的Message。一开始MessageQueue里面的Message都是NULL的。当Handler.sendMessage(Message)到MessageQueue,该函数里面设置了那个Message对象的target属性是当前的Handler对象。随后Looper取出了那个Message,则调用该Message的target指向的Hander的dispatchMessage函数对Message进行处理。在dispatchMessage方法里,如何处理Message则由用户指定,三个判断,优先级从高到低:Message里面的Callback,一个实现了Runnable接口的对象,其中run函数做处理工作;Handler里面的mCallback指向的一个实现了Callback接口的对象,由其handleMessage进行处理;理消息Handler对象对应的类继承并实现了其中handleMessage函数,通过这个实现的handleMessage函数处理消息。Handler处理完该Message(updateUI)后,Looper则设置该Message为NULL,以便回收!Android消息机制一几个类之间的相互作用:一个线程可以产生一个Looper对象,由它来管理此线程里的MessageQueue(消息队列)。你可以构造Handler对象来与Looper沟通,以便push新消息到MessageQueue里;或者接收Looper(从MessageQueue取出)所送来的消息。UIthread通常就是mainthread,而Android启动程序时会替它建立一个MessageQueue每一个线程里可含有一个Looper对象以及一个MessageQueue数据结构。在你的应用程序里,可以定义Handler的子类别来接收Looper所送出的消息子线程之间通信在Android程序里,新诞生一个线程,或执行(Thread)时,并不会自动建立其MessageLoop。同时,Android里并没有Global的MessageQueue数据结构,例如,不同APK里的对象不能透过MassageQueue来交换讯息(Message)。例如:线程A的Handler对象可以传递消息给别的线程,让别的线程B或C等能送消息来给线程A(存于A的MessageQueue里)。线程A的MessageQueue里的讯息,只有线程A所属的对象可以处理。使用Looper.myLooper可以取得当前线程的Looper对象。使用Looper.getMainLooper可以取得main线程的Looper对象使用mHandler=newMyHandler(Looper.myLooper());可用来构造当前线程的Handler对象;其中,MyHandler是自已实现的Handler的子类别。使用mHandler=newMyHandler(Looper.getMainLoop
本文标题:android多线程处理
链接地址:https://www.777doc.com/doc-3612727 .html