摘 要:Android是一种基于Linux的自由及开放源代码的操作系统,主要使用于便携设备,如智能手机和平板电脑。Android系统属于单线程模型,子线程不能控制UI主线程。
关键词:Android,handler,aysncTask
1. 前言
1.1 Android主线程
在一个Android 程序开始运行的时候,会单独启动一个Process。默认的情况下,所有这个程序中的Activity或者Service(Service和 Activity只是Android提供的Components中的两种,除此之外还有Content Provider和Broadcast Receiver)都会跑在这个Process。
一个Android 程序默认情况下也只有一个Process,但一个Process下却可以有许多个Thread。
在这么多Thread当中,有一个Thread,我们称之为UI Thread。UI Thread在Android程序运行的时候就被创建,是一个Process当中的主线程Main Thread,主要是负责控制UI界面的显示、更新和控件交互。在Android程序创建之初,一个Process呈现的是单线程模型,所有的任务都在一个线程中运行(Android的UI是单线程(Single-threaded)的)。因此,我们认为,UI Thread所执行的每一个函数,所花费的时间都应该是越短越好。而其他比较费时的工作(访问网络,下载数据,查询数据库等),都应该交由子线程去执行,以免阻塞主线程。
1.2 Android子线程
Android禁止其他子线程来更新由UI thread创建的view(即不可以在子线程中更新 UI),否则会报错或者有异常信息CalledFromWrongThreadException:android.view.ViewRoot$CalledFromWrongThreadException:Only the original thread that created a view hierarchy can touch its views.
2. Android子线程主线程的通信方法
在单线程模型下,为了解决主线程/子线程通信的问题,Android中有以下两种解决方法。
2.1 Handler
Android设计了一个Message Queue(消息队列),线程间可以通过该Message Queue并结合Handler和Looper组件进行信息交换:诞生一个主线程的Handler,当做Listener去让子线程能将信息Push到主线程的MessageQuene里,以便触发主线程的handlerMessage()函数,让主线程知道子线程的状态,并在主线程更新UI。
使用的优点:
- 结构清晰,功能定义明确
- 对于多个后台任务时,简单,清晰
使用的缺点:
- 在单个后台异步处理时,显得代码过多,结构过于复杂(相对性)
在Handler 异步实现时,涉及到 Handler, Looper, Message,Thread四个对象,实现异步的流程是主线程启动Thread(子线程)àthread(子线程)运行并生成Message-àLooper获取Message并传递给HandleràHandler逐个获取Looper中的Message,并进行UI变更。
2.1.1详情
- Message Queue
Message Queue是一个消息队列,用来存放通过Handler发布的消息。消息队列通常附属于某一个创建它的线程,可以通过Looper.myQueue()得到当前线程的消息队列。Android在第一启动程序时会默认会为UI thread创建一个关联的消息队列,用来管理程序的一些上层组件,activities,broadcast receivers 等等。也可以在自己的子线程中创建Handler与UI thread通讯。
- Handler