name="android.permission.RECEIVE_SMS">
两种注册类型的区别是:
1)第一种不是常驻型广播,也就是说广播跟随程序的生命周期。
2)第二种是常驻型,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行。
10. 请解释下在单线程模型中Message、Handler、MessageQueue、Looper之间的关系。
1.Android进程
当一个程序第一次启动的时候,Android会启动一个LINUX进程和一个主线程。
默认的情况下,所有该程序的组件都将在该进程和线程中运行。
同时,Android会为每个应用程序分配一个单独的LINUX用户。
Android会尽量保留一个正在运行进程,只在内存资源出现不足时,Android会尝试停止一些进程从而释放足够的资源给其他新的进程使用,也能保证用户正在访问的当前进程有足够的资源去及时地响应用户的事件。
Android会根据进程中运行的组件类别以及组件的状态来判断该进程的重要性,Android会首先停止那些不重要的进程。
按照重要性从高到低一共有五个级别:
前台进程
前台进程是用户当前正在使用的进程。
只有一些前台进程可以在任何时候都存在。
他们是最后一个被结束的,当内存低到根本连他们都不能运行的时候。
一般来说,在这种情况下,设备会进行内存调度,中止一些前台进程来保持对用户交互的响应。
可见进程
可见进程不包含前台的组件但是会在屏幕上显示一个可见的进程是的重要程度很高,除非前台进程需要获取它的资源,不然不会被中止。
服务进程
运行着一个通过startService()方法启动的service,这个service不属于上面提到的2种更高重要性的。
service所在的进程虽然对用户不是直接可见的,但是他们执行了用户非常关注的任务(比如播放mp3,从网络下载数据)。
只要前台进程和可见进程有足够的内存,系统不会回收他们。
后台进程
运行着一个对用户不可见的activity(调用过onStop()方法).这些进程对用户体验没有直接的影响,可以在服务进程、可见进程、前台进程需要内存的时候回收。
通常,系统中会有很多不可见进程在运行,他们被保存在LRU(leastrecentlyused)列表中,以便内存不足的时候被第一时间回收。
如果一个activity正确的执行了它的生命周期,关闭这个进程对于用户体验没有太大的影响。
空进程
未运行任何程序组件。
运行这些进程的唯一原因是作为一个缓存,缩短下次程序需要重新使用的启动时间。
系统经常中止这些进程,这样可以调节程序缓存和系统缓存的平衡。
Android对进程的重要性评级的时候,选取它最高的级别。
另外,当被另外的一个进程依赖的时候,某个进程的级别可能会增高。
一个为其他进程服务的进程永远不会比被服务的进程重要级低。
因为服务进程比后台activity进程重要级高,因此一个要进行耗时工作的activity最好启动一个service来做这个工作,而不是开启一个子进程――特别是这个操作需要的时间比activity存在的时间还要长的时候。
例如,在后台播放音乐,向网上上传摄像头拍到的图片,使用service可以使进程最少获取到“服务进程”级别的重要级,而不用考虑activity目前是什么状态。
broadcastreceivers做费时的工作的时候,也应该启用一个服务而不是开一个线程。
2.单线程模型
当一个程序第一次启动时,Android会同时启动一个对应的主线程(MainThread),主线程主要负责处理与UI相关的事件,如用户的按键事件,用户接触屏幕的事件以及屏幕绘图事件,并把相关的事件分发到对应的组件进行处理。
所以主线程通常又被叫做UI线程。
在开发Android应用时必须遵守单线程模型的原则:
AndroidUI操作并不是线程安全的并且这些操作必须在UI线程中执行。
2.1子线程更新UI
Android的UI是单线程(Single-threaded)的。
为了避免拖住GUI,一些较费时的对象应该交给独立的线程去执行。
如果幕后的线程来执行UI对象,Android就会发出错误讯息
CalledFromWrongThreadException。
以后遇到这样的异常抛出时就要知道怎么回事了!
2.2MessageQueue
在单线程模型下,为了解决类似的问题,Android设计了一个MessageQueue(消息队列),线程间可以通过该MessageQueue并结合Handler和Looper组件进行信息交换。
下面将对它们进行分别介绍:
1.Message
Message消息,理解为线程间交流的信息,处理数据后台线程需要更新UI,则发送Message内含一些数据给UI线程。
2.Handler
Handler处理者,是Message的主要处理者,负责Message的发送,Message内容的执行处理。
后台线程就是通过传进来的Handler对象引用来sendMessage(Message)。
而使用Handler,需要implement该类的handleMessage(Message)
方法,它是处理这些Message的操作内容,例如UpdateUI。
通常需要子类化Handler来实现handleMessage方法。
3.MessageQueue
MessageQueue消息队列,用来存放通过Handler发布的消息,按照先进先出执行。
每个messagequeue都会有一个对应的Handler。
Handler会向messagequeue通过两种方法发送消息:
sendMessage或post。
这两种消息都会插在messagequeue队尾并按先进先出执行。
但通过这两种方法发送的消息执行的方式略有不同:
通过sendMessage发送的是一个message对象,会被Handler的handleMessage()函数处理;而通过post方法发送的是一个runnable对象,则会自己执行。
4.Looper
Looper是每条线程里的MessageQueue的管家。
Android没有Global的MessageQueue,而Android会自动替主线程(UI线程)建立MessageQueue,但在子线程里并没有建立MessageQueue。
所以调用Looper.getMainLooper()得到的主线程的Looper不为NULL,但调用Looper.myLooper()得到当前线程的Looper就有可能为NULL。
对于子线程使用Looper,APIDoc提供了正确的使用方法:
这个Message机制的大概流程:
1.在Looper.loop()方法运行开始后,循环地按照接收顺序取出MessageQueue里面的非NULL的Message。
2.一开始MessageQueue里面的Message都是NULL的。
当Handler.sendMessage(Message)到MessageQueue,该函数里面设置了那个Message对象的target属性是当前的Handler对象。
随后Looper取出了那个Message,则调用该Message的target指向的Hander的dispatchMessage函数对Message进行处理。
在dispatchMessage方法里,如何处理Message则由用户指定,三个判断,优先级从高到低:
1)Message里面的Callback,一个实现了Runnable接口的对象,其中run函数做处理工作;
2)Handler里面的mCallback指向的一个实现了Callback接口的对象,由其handleMessage进行处理;
3)处理消息Handler对象对应的类继承并实现了其中handleMessage函数,通过这个实现的handleMessage函数处理消息。
由此可见,我们实现的handleMessage方法是优先级最低的!
3.Handler处理完该Message(updateUI)后,Looper则设置该Message为NULL,以便回收!
在网上有很多文章讲述主线程和其他子线程如何交互,传送信息,最终谁来执行处理信息之类的,个人理解是最简单的方法——判断Handler对象里面的Looper对象是属于哪条线程的,则由该线程来执行!
1.当Handler对象的构造函数的参数为空,则为当前所在线程的Looper;
2.Looper.getMainLooper()得到的是主线程的Looper对象,Looper.myLooper()得到的是当前线程的Looper对象。
11. AIDL的全称是什么?
如何工作?
能处理哪些类型的数据?
12. 请解释下Android程序运行时权限与文件系统权限的区别。
(EditedbySodino)
13. 系统上安装了多种浏览器,能否指定某浏览器访问指定页面?
请说明原由。
14. 有一个一维整型数组int[]data保存的是一张宽为width,高为height的图片像素值信息。
请写一个算法,将该图片所有的白色不透明(0xffffffff)像素点的透明度调整为50%。
暂时没有找到!
1、什么是ANR如何避免它?
ANR:
ApplicationNotResponding,五秒
在Android中,活动管理器和窗口管理器这两个系统服务负责监视应用程序的响应。
当出现下列情况时,Android就会显示ANR对话框了:
对输入事件(如按键、触摸屏事件)的响应超过5秒
意向接受器(intentReceiver)超过10秒钟仍未执行完毕
Android应用程序完全运行在一个独立的线程中(例如main)。
这就意味着,任何在主线程中运行的,需要消耗大量时间的操作都会引发ANR。
因为此时,你的应用程序已经没有机会去响应输入事件和意向广播(Intentbroadcast)。
因此,任何运行在主线程中的方法,都要尽可能的只做少量的工作。
特别是活动生命周期中的重要方法如onCreate()和onResume()等更应如此。
潜在的比较耗时的操作,如访问网络和数据库;或者是开销很大的计算,比如改变位图的大小,需要在一个单独的子线程中完成(或者是使用异步请求,如数据库操作)。
但这并不意味着你的主线程需要进入阻塞状态已等待子线程结束--也不需要调用Therad.wait()或者Thread.sleep()方法。
取而代之的是,主线程为子线程提供一个句柄(Handler),让子线程在即将结束的时候调用它(xing:
可以参看Snake的例子,这种方法与以前我们所接触的有所不同)。
使用这种方法涉及你的应用程序,能够保证你的程序对输入保持良好的响应,从而