- 浏览: 182273 次
- 性别:
- 来自: 云南
文章分类
最新评论
-
chencangui:
楼主能分享下源码吗?蟹蟹了
Android使用VideoView播放网络视频 -
liulongke:
表示看完完全没看出来是繁体字的默默走过。。。
PagerAdapter用法 -
Alexia23:
很赞很详细!
JAVA列出目录下所有的文件&文件夹 -
snso001:
繁体字恶心了。。。
PagerAdapter用法 -
wushanlin123:
楼主,你的繁体字让我蛋碎了一地
PagerAdapter用法
即使你的应用程序是快速且响应灵敏的,但一些设计仍然会给用户造成问题——与其它应用程序或对话框未事先计划的交互,意外的数据丢失,意料之外的阻塞等 等。避免这些问题,有助于理解应用程序运行的上下文和系统的交互过程,而这些又正影响着你的应用程序。简而言之,你应该竭尽全力去开发一个与系统和其它应 用程序流畅交互的应用程序。
一个常见的流畅问题是,一个应用程序的后台处理——例如,一个Service或者BroadcastReceiver——弹出一个对话框来响应一些事 件。这可能看起来没啥大碍,尤其是你在模拟器上单独地构建和测试你的应用程序的时候。然而,当你的应用程序运行在真机上时,有可能你的应用程序在没有获得 用户焦点时后台处理显示了一个对话框。因此,可能会出现在活跃的应用程序后方显示了你的应用程序的对话框,或者从当前应用程序夺取焦点显示了一个对话框, 而不管当前用户正在做什么(例如,正在打电话)。那种行为,对应用程序或用户来说,就不应该出现。
为了避免这些问题,你的应用程序应该使用合适的系统资源来通知用户——Notification类。使用Notification,你的应用程序可以在状态栏显示一个icon来通知用户已经发生的事情,而不是夺取焦点和打断用户。
另一个流畅问题的例子是未能正确实现Activity的onPause()和其它生命周期方法而造成意外丢失了状态或用户数据。又或者,如果你的应用 程序想暴露数据给其它应用程序使用,你应该通过ContentProvider来暴露,而不是(举例)通过一个可读的原始文件或数据库来实现。
这些例子的共同点是它们都应该与系统和其它应用程序协作好。Android系统设计时,就把应用程序看作是一堆松散耦合的组件,而不是一堆黑盒代码。 作为开发者来说,允许我们把整个系统看作是更大的组件集合。这有益于我们可以与其它应用程序进行清晰无缝的集成,因此,作为回报,我们应该更好的设计我们 的代码。
这篇文章将讨论常见的流畅问题以及如何避免它们。它将囊括这些主题:
1) 别丢弃数据
2) 不要暴露原始数据
3) 不要打断用户
4) 有太多事情要做?在线程里做
5) 不要让一个Activity超负荷
6) 扩展系统主题
7) 设计你的UI可以应付多屏幕分辨率
8) 假设网络很慢
9) 不要假定触摸屏或键盘
10) 节省设备电池
1)别丢弃数据
一定要记住Android是一个移动平台。可以显而易见地说,其它Activity(例如,“Incoming Phone Call”应用程序)可能会在任何时候弹出来遮盖你的Activity,记住这个事实很重要。因为这个过程将触发 onSaveInstanceState()和onPause()方法,并可能导致你的应用程序被杀死。
如果用户在你的应用程序中正在编辑数据时,其它Activity出现了,这时,你的应用程序被杀死时可能丢失那些数据。当然了,除非你事先保存了正在 进行的工作。“Android方式”是这样做的:能接收和编辑用户输入的Android应用程序应该重写onSaveInstanceState()方 法,并以恰当的方式保存它们的状态。当用户重新访问应用程序时,她能得到她的数据。
进行这种处理方式最经典的例子是mail应用程序。如果用户正在输入email,这时其它Activity启动了,mail应用程序应该把正在编辑的email以草稿的方式保存起来。
2)不要暴露原始数据
如果你不想穿着内衣在大街上溜达的话,你的数据也不应该这样。尽管可能存在暴露应用程序的某种形式给其它应用程序,但这通常不是最好的主意。暴露原始数据,要求其它应用程序能够理解你的数据的格式;如果你变更了格式,那么,你将破坏那些没有进行同步更新的应用程序。
“Android方式”是创建一个ContentProvider,以一种清晰的、深思熟虑的和可维护的API方式暴露你的数据给其它应用程序。使用 ContentProvider,就好像是插入Java接口来分离和组装两片高耦合的代码。这意味着你可以修改数据的内部格式,而不用修改由 ContentProvider暴露的接口,这样,也不会影响其它应用程序。
3)不要打断用户
如果用户正在运行一个应用程序(例如,Phone程序),断定对用户操作的目的才是安全的。这也就是为什么必须避免创建Activity,而是直接在当前的Activity中响应用户的输入。
那就是说,不要在BroadcastReceiver或在后台运行的Service中调用callActivity()。这么做会中断当前运行的应用 程序,并导致用户恼怒。也许更糟糕的是,你的Activity可能成为“按键强盗”,窃取了用户要提供给前一个Activity的输入。视乎你的应用程序 所做的事情,这可能是个坏消息。
不选择在后台直接创建Activity UI,取而代之的是,应该使用NotificationManager来设置Notification。它们会出现在状态栏,并且用户可以在他空闲的时候点击它们,来查看你的应用程序向他显示了什么。
(注意,如果你的Activity已经在前台了,以上将不适用:这时,对于用户的输入,用户期望的是看到下一个Activity来响应。)
4)有太多事情要做?在线程里做
如果你的应用程序需要执行一些昂贵或耗时的计算的话,你应该尽可能地将它挪到线程里。这将阻止向用户显示可怕的“Application Not Responding”对话框,如果不这样做,最终的结果会导致你的应用程序完全终止。
一般情况下,Activity中的所有代码,包括它的View,都运行在相同的线程里。在这个线程里,还需要处理UI事件。例如,当用户按下一个按 键,一个key-down事件就会添加到Activity的主线程队列里。事件处理系统需要很快让这个事件出列并得到处理;如果没有,系统数秒后会认为应 用程序已经挂起并为用户提供杀死应用程序的机会。
如果有耗时的代码,内联在Activity上运行也就是运行在事件处理线程里,这在很大程度上阻塞了事件处理。这会延迟输入处理,并导致ANR对话框。为了避免这个,把你的计算移到线程里。在响应灵敏性设计的文章里已经讨论了如何做。
5)不要让一个Activity超负荷
任何值得使用的应用程序都可能有几个不同的屏幕。当设计UI屏幕时,请一定要使用多个Activity对象实例。
依赖于你的开发背景,你可能理解Activity类似于Java Applet,它是你应用程序的入口点。然而,那并不精确:Applet子类是一个Java Applet的单一入口点,而一个Activity应该看作是你的应用程序多个潜在入口点之一。你的“main”Activity和其它之间的唯一不同点 是“main”Activity正巧是在AndroidManifest.xml文件中唯一对“android.intent.action.MAIN” 动作感兴趣的Activity。
因此,当设计你的应用程序的时候,把你的应用程序看作是Activity对象的集合。从长远来看,这会使得你的代码更加方便维护。
6)扩展系统主题
当谈到UI观感时,巧妙地交融非常重要。用户在使用与自己期望相反的UI的应用程序时,会产生不愉快的感觉。当设计你的UI时,你应该尽量避免太多自 己的主题。相反的,使用同一个主题。你可以重写或扩展你需要的主题部分,但至少在与其它应用程序相同的UI基础上开始。详细请参照“应用风格和主题”部 分。
7)设计你的UI可以应对多屏幕分辨率
不同的Android设备可能支持不同的屏幕分辨率。甚至一些可以自己变更分辨率,例如,切换到风景模式。确保你的布局和图片能足够灵活地在不同的设备屏幕上正常显示。
幸运的是,这很容易做到。简而言之,你需要做的是为主要分辨率提供不同版本的作品,然后为不同的尺寸设计你的布局。(例如,避免使用硬编码位置而使用相对布局。)如果那样做的话,系统会处理剩下的部分,而且你的应用程序在任何设备上都看起来很棒。
8)假设网络很慢
Android设备会有多种网络连接选项。所有的都提供数据访问,但之间肯定有更快的。其中,速度最慢的是GPRS,GSM网络的非3G数据服务。即使具备3G能力的设备在非3G的网络上也会花费很多的时间,所以,网络很慢仍然是一个长期存在的事实。
这就是为什么你应该按照最小化的网络访问和带宽来编写你的代码。你不能假设网络是快速的,所以,你应该总是计划它是慢的。如果你的用户碰巧在一个快速 的网络上,那很好——他们的用户体验会提升。你要避免相反的情形:在不同的地点和不同时间,应用程序有时可用,有时慢得令人抓狂,这样的程序可能不会受欢 迎。
还有一个潜在的地方是,如果你正在使用模拟器,那么你很容易受它迷糊,因为模拟器使用电脑的网络连接。这比手机网络快很多,所以,你需要修改模拟器设 定来模拟较低的网络速度。你可以在Eclipse中做到这点,在启动选项的模拟器设置页里设置或者在启动模拟器时通过命令行选项设置。
9)不要假定触摸屏或键盘
Android可以支持多种外观形状。也就是说,一些Android设备拥有全“QWERTY”键盘,而其它可能会有40键、12键或其它键盘设置。同样的,一些设备可能有触摸屏,但一些也会没有。
当创建你的应用程序的时候,记住这一点。不要假定特定的键盘布局——除非你真的想限定你的应用程序只运行在某些设备上。
10)节省设备电池
如果移动设备经常插在墙上,那么,它也就不是很“移动”。移动设备是电池供电的,如果我们能让每次充电的电池使用得更持久一些,那么每个人都会更加开 心——尤其是用户。其中两大耗电硬件是处理器和无线;这也就是我们为什么要写尽可能少做工作、尽可能少去使用网络的应用程序的重要原因。
如何让你的应用程序最小化的占用处理器,归根结底还是要写高效代码。为了减少无线的电量消耗,确保对错误条件进行正确的处理,并只获取你要的东西。例 如,如果某一个网络操作失败了,不要不断地进行重试。如果失败了一次,有可能是用户不受欢迎,因此,如果你再以正确的方式操作,有可能还会失败;所有你做 的都是在浪费电池。
用户是相当聪明的:如果你的程序高耗电,他们是一定会发现的。到那个时点,你唯一可以确定的是,你的程序将很快被卸载掉。
可能会存在这样的情况,你写的代码通过了世界上所有的性能测试,但当用户尝试使用你的应用程序时,仍然让用户感到不爽。应用程序响应不够灵敏的地方包括——反映迟钝,挂起或冻结很长时间,或者需要花费很长的时间来处理输入。
在 Android上,如果你的应用程序有一段时间响应不够灵敏,系统会向用户显示一个对话框,这个对话框称作应用程序无响应 (ANR:Application Not Responding)对话框。用户可以选择让程序继续运行,但是,他们在使用你的应用程序时,并不希望每次都要处理这个对话框。因此,在程序里对响应性 能的设计很重要,这样,系统不会显示ANR给用户。
一般说来,如果应用程序不能响应用户输入的话,系统会显示一个ANR。例如,一个应用程序阻塞在一些I/O操作上(通常是网络访问),这时,应用程序 的主线程就不能再处理用户的输入事件。经过一定的时间后,系统认为应用程序已经挂起,并显示ANR来让用户选择杀死应用程序。
相似地,如果你的应用程序花费太多的时间来构建详细的内存结构,或者也许是在游戏里花费太多时间来计算下一步移动,这时,系统会认为你的应用程序已经挂起。因此,确保这些计算是高效的往往很重要,但即使是最高效的代码仍然需要花费时间来运行。
在这两种情况下,解决的方法通常是创建一个子线程,然后在线程里做你的大部分工作。这能让主线程(驱动UI事件循环)保持运行,并阻止系统认为你的代 码已经冻结。因为这些线程通常是在类级别上完成的,因此,你可以认为响应性能问题是一个类的问题。(与基本性能相比而言,基本性能问题认为是方法级别的问 题)
这篇文章将讨论Android系统如何判断一个应用程序处于无响应状态,并为保证应用程序的响应性提供向导。
这篇文章囊括这些主题:
什么引发了ANR?
如何避免ANR?
增强响应灵敏性
1)什么引发了ANR?
在Android里,应用程序的响应性是由Activity Manager和Window Manager系统服务监视的。当它监测到以下情况中的一个时,Android就会针对特定的应用程序显示ANR:
在5秒内没有响应输入的事件(例如,按键按下,屏幕触摸)
BroadcastReceiver在10秒内没有执行完毕
一个ANR对话框显示给用户
2)如何避免ANR?
考虑上面的ANR定义,让我们来研究一下为什么它会在Android应用程序里发生和如何最佳构建应用程序来避免ANR。
Android应用程序通常是运行在一个单独的线程(例如,main)里。这意味着你的应用程序所做的事情如果在主线程里占用了太长的时间的话,就会引发ANR对话框,因为你的应用程序并没有给自己机会来处理输入事件或者Intent广播。
因此,运行在主线程里的任何方法都尽可能少做事情。特别是,Activity应该在它的关键生命周期方法(如onCreate()和 onResume())里尽可能少的去做创建操作。潜在的耗时操作,例如网络或数据库操作,或者高耗时的计算如改变位图尺寸,应该在子线程里(或者以数据 库操作为例,通过异步请求的方式)来完成。然而,不是说你的主线程阻塞在那里等待子线程的完成——也不是调用Thread.wait()或是 Thread.sleep()。替代的方法是,主线程应该为子线程提供一个Handler,以便完成时能够提交给主线程。以这种方式设计你的应用程序,将 能保证你的主线程保持对输入的响应性并能避免由于5秒输入事件的超时引发的ANR对话框。这种做法应该在其它显示UI的线程里效仿,因为它们都受相同的超 时影响。
IntentReceiver 执行时间的特殊限制意味着它应该做:在后台里做小的、琐碎的工作如保存设定或者注册一个Notification。和在主线程里调用的其它方法一样,应用 程序应该避免在BroadcastReceiver里做耗时的操作或计算。但不再是在子线程里做这些任务(因为BroadcastReceiver的生命 周期短),替代的是,如果响应Intent广播需要执行一个耗时的动作的话,应用程序应该启动一个Service。顺便提及一句,你也应该避免在 Intent Receiver里启动一个Activity,因为它会创建一个新的画面,并从当前用户正在运行的程序上抢夺焦点。如果你的应用程序在响应Intent广 播时需要向用户展示什么,你应该使用Notification Manager来实现。
3)增强响应灵敏性
一般来说,在应用程序里,100到200ms是用户能感知阻滞的时间阈值。因此,这里有一些额外的技巧来避免ANR,并有助于让你的应用程序看起来有 响应性.如果你的应用程序为响应用户输入正在后台工作的话,可以显示工作的进度(ProgressBar和ProgressDialog对这种情况来说很 有用)。特别是游戏,在子线程里做移动的计算。如果你的应用程序有一个耗时的初始化过程的话,考虑可以显示一个Splash Screen或者快速显示主画面并异步来填充这些信息。在这两种情况下,你都应该显示正在进行的进度,以免用户认为应用程序被冻结了。
一个常见的流畅问题是,一个应用程序的后台处理——例如,一个Service或者BroadcastReceiver——弹出一个对话框来响应一些事 件。这可能看起来没啥大碍,尤其是你在模拟器上单独地构建和测试你的应用程序的时候。然而,当你的应用程序运行在真机上时,有可能你的应用程序在没有获得 用户焦点时后台处理显示了一个对话框。因此,可能会出现在活跃的应用程序后方显示了你的应用程序的对话框,或者从当前应用程序夺取焦点显示了一个对话框, 而不管当前用户正在做什么(例如,正在打电话)。那种行为,对应用程序或用户来说,就不应该出现。
为了避免这些问题,你的应用程序应该使用合适的系统资源来通知用户——Notification类。使用Notification,你的应用程序可以在状态栏显示一个icon来通知用户已经发生的事情,而不是夺取焦点和打断用户。
另一个流畅问题的例子是未能正确实现Activity的onPause()和其它生命周期方法而造成意外丢失了状态或用户数据。又或者,如果你的应用 程序想暴露数据给其它应用程序使用,你应该通过ContentProvider来暴露,而不是(举例)通过一个可读的原始文件或数据库来实现。
这些例子的共同点是它们都应该与系统和其它应用程序协作好。Android系统设计时,就把应用程序看作是一堆松散耦合的组件,而不是一堆黑盒代码。 作为开发者来说,允许我们把整个系统看作是更大的组件集合。这有益于我们可以与其它应用程序进行清晰无缝的集成,因此,作为回报,我们应该更好的设计我们 的代码。
这篇文章将讨论常见的流畅问题以及如何避免它们。它将囊括这些主题:
1) 别丢弃数据
2) 不要暴露原始数据
3) 不要打断用户
4) 有太多事情要做?在线程里做
5) 不要让一个Activity超负荷
6) 扩展系统主题
7) 设计你的UI可以应付多屏幕分辨率
8) 假设网络很慢
9) 不要假定触摸屏或键盘
10) 节省设备电池
1)别丢弃数据
一定要记住Android是一个移动平台。可以显而易见地说,其它Activity(例如,“Incoming Phone Call”应用程序)可能会在任何时候弹出来遮盖你的Activity,记住这个事实很重要。因为这个过程将触发 onSaveInstanceState()和onPause()方法,并可能导致你的应用程序被杀死。
如果用户在你的应用程序中正在编辑数据时,其它Activity出现了,这时,你的应用程序被杀死时可能丢失那些数据。当然了,除非你事先保存了正在 进行的工作。“Android方式”是这样做的:能接收和编辑用户输入的Android应用程序应该重写onSaveInstanceState()方 法,并以恰当的方式保存它们的状态。当用户重新访问应用程序时,她能得到她的数据。
进行这种处理方式最经典的例子是mail应用程序。如果用户正在输入email,这时其它Activity启动了,mail应用程序应该把正在编辑的email以草稿的方式保存起来。
2)不要暴露原始数据
如果你不想穿着内衣在大街上溜达的话,你的数据也不应该这样。尽管可能存在暴露应用程序的某种形式给其它应用程序,但这通常不是最好的主意。暴露原始数据,要求其它应用程序能够理解你的数据的格式;如果你变更了格式,那么,你将破坏那些没有进行同步更新的应用程序。
“Android方式”是创建一个ContentProvider,以一种清晰的、深思熟虑的和可维护的API方式暴露你的数据给其它应用程序。使用 ContentProvider,就好像是插入Java接口来分离和组装两片高耦合的代码。这意味着你可以修改数据的内部格式,而不用修改由 ContentProvider暴露的接口,这样,也不会影响其它应用程序。
3)不要打断用户
如果用户正在运行一个应用程序(例如,Phone程序),断定对用户操作的目的才是安全的。这也就是为什么必须避免创建Activity,而是直接在当前的Activity中响应用户的输入。
那就是说,不要在BroadcastReceiver或在后台运行的Service中调用callActivity()。这么做会中断当前运行的应用 程序,并导致用户恼怒。也许更糟糕的是,你的Activity可能成为“按键强盗”,窃取了用户要提供给前一个Activity的输入。视乎你的应用程序 所做的事情,这可能是个坏消息。
不选择在后台直接创建Activity UI,取而代之的是,应该使用NotificationManager来设置Notification。它们会出现在状态栏,并且用户可以在他空闲的时候点击它们,来查看你的应用程序向他显示了什么。
(注意,如果你的Activity已经在前台了,以上将不适用:这时,对于用户的输入,用户期望的是看到下一个Activity来响应。)
4)有太多事情要做?在线程里做
如果你的应用程序需要执行一些昂贵或耗时的计算的话,你应该尽可能地将它挪到线程里。这将阻止向用户显示可怕的“Application Not Responding”对话框,如果不这样做,最终的结果会导致你的应用程序完全终止。
一般情况下,Activity中的所有代码,包括它的View,都运行在相同的线程里。在这个线程里,还需要处理UI事件。例如,当用户按下一个按 键,一个key-down事件就会添加到Activity的主线程队列里。事件处理系统需要很快让这个事件出列并得到处理;如果没有,系统数秒后会认为应 用程序已经挂起并为用户提供杀死应用程序的机会。
如果有耗时的代码,内联在Activity上运行也就是运行在事件处理线程里,这在很大程度上阻塞了事件处理。这会延迟输入处理,并导致ANR对话框。为了避免这个,把你的计算移到线程里。在响应灵敏性设计的文章里已经讨论了如何做。
5)不要让一个Activity超负荷
任何值得使用的应用程序都可能有几个不同的屏幕。当设计UI屏幕时,请一定要使用多个Activity对象实例。
依赖于你的开发背景,你可能理解Activity类似于Java Applet,它是你应用程序的入口点。然而,那并不精确:Applet子类是一个Java Applet的单一入口点,而一个Activity应该看作是你的应用程序多个潜在入口点之一。你的“main”Activity和其它之间的唯一不同点 是“main”Activity正巧是在AndroidManifest.xml文件中唯一对“android.intent.action.MAIN” 动作感兴趣的Activity。
因此,当设计你的应用程序的时候,把你的应用程序看作是Activity对象的集合。从长远来看,这会使得你的代码更加方便维护。
6)扩展系统主题
当谈到UI观感时,巧妙地交融非常重要。用户在使用与自己期望相反的UI的应用程序时,会产生不愉快的感觉。当设计你的UI时,你应该尽量避免太多自 己的主题。相反的,使用同一个主题。你可以重写或扩展你需要的主题部分,但至少在与其它应用程序相同的UI基础上开始。详细请参照“应用风格和主题”部 分。
7)设计你的UI可以应对多屏幕分辨率
不同的Android设备可能支持不同的屏幕分辨率。甚至一些可以自己变更分辨率,例如,切换到风景模式。确保你的布局和图片能足够灵活地在不同的设备屏幕上正常显示。
幸运的是,这很容易做到。简而言之,你需要做的是为主要分辨率提供不同版本的作品,然后为不同的尺寸设计你的布局。(例如,避免使用硬编码位置而使用相对布局。)如果那样做的话,系统会处理剩下的部分,而且你的应用程序在任何设备上都看起来很棒。
8)假设网络很慢
Android设备会有多种网络连接选项。所有的都提供数据访问,但之间肯定有更快的。其中,速度最慢的是GPRS,GSM网络的非3G数据服务。即使具备3G能力的设备在非3G的网络上也会花费很多的时间,所以,网络很慢仍然是一个长期存在的事实。
这就是为什么你应该按照最小化的网络访问和带宽来编写你的代码。你不能假设网络是快速的,所以,你应该总是计划它是慢的。如果你的用户碰巧在一个快速 的网络上,那很好——他们的用户体验会提升。你要避免相反的情形:在不同的地点和不同时间,应用程序有时可用,有时慢得令人抓狂,这样的程序可能不会受欢 迎。
还有一个潜在的地方是,如果你正在使用模拟器,那么你很容易受它迷糊,因为模拟器使用电脑的网络连接。这比手机网络快很多,所以,你需要修改模拟器设 定来模拟较低的网络速度。你可以在Eclipse中做到这点,在启动选项的模拟器设置页里设置或者在启动模拟器时通过命令行选项设置。
9)不要假定触摸屏或键盘
Android可以支持多种外观形状。也就是说,一些Android设备拥有全“QWERTY”键盘,而其它可能会有40键、12键或其它键盘设置。同样的,一些设备可能有触摸屏,但一些也会没有。
当创建你的应用程序的时候,记住这一点。不要假定特定的键盘布局——除非你真的想限定你的应用程序只运行在某些设备上。
10)节省设备电池
如果移动设备经常插在墙上,那么,它也就不是很“移动”。移动设备是电池供电的,如果我们能让每次充电的电池使用得更持久一些,那么每个人都会更加开 心——尤其是用户。其中两大耗电硬件是处理器和无线;这也就是我们为什么要写尽可能少做工作、尽可能少去使用网络的应用程序的重要原因。
如何让你的应用程序最小化的占用处理器,归根结底还是要写高效代码。为了减少无线的电量消耗,确保对错误条件进行正确的处理,并只获取你要的东西。例 如,如果某一个网络操作失败了,不要不断地进行重试。如果失败了一次,有可能是用户不受欢迎,因此,如果你再以正确的方式操作,有可能还会失败;所有你做 的都是在浪费电池。
用户是相当聪明的:如果你的程序高耗电,他们是一定会发现的。到那个时点,你唯一可以确定的是,你的程序将很快被卸载掉。
可能会存在这样的情况,你写的代码通过了世界上所有的性能测试,但当用户尝试使用你的应用程序时,仍然让用户感到不爽。应用程序响应不够灵敏的地方包括——反映迟钝,挂起或冻结很长时间,或者需要花费很长的时间来处理输入。
在 Android上,如果你的应用程序有一段时间响应不够灵敏,系统会向用户显示一个对话框,这个对话框称作应用程序无响应 (ANR:Application Not Responding)对话框。用户可以选择让程序继续运行,但是,他们在使用你的应用程序时,并不希望每次都要处理这个对话框。因此,在程序里对响应性 能的设计很重要,这样,系统不会显示ANR给用户。
一般说来,如果应用程序不能响应用户输入的话,系统会显示一个ANR。例如,一个应用程序阻塞在一些I/O操作上(通常是网络访问),这时,应用程序 的主线程就不能再处理用户的输入事件。经过一定的时间后,系统认为应用程序已经挂起,并显示ANR来让用户选择杀死应用程序。
相似地,如果你的应用程序花费太多的时间来构建详细的内存结构,或者也许是在游戏里花费太多时间来计算下一步移动,这时,系统会认为你的应用程序已经挂起。因此,确保这些计算是高效的往往很重要,但即使是最高效的代码仍然需要花费时间来运行。
在这两种情况下,解决的方法通常是创建一个子线程,然后在线程里做你的大部分工作。这能让主线程(驱动UI事件循环)保持运行,并阻止系统认为你的代 码已经冻结。因为这些线程通常是在类级别上完成的,因此,你可以认为响应性能问题是一个类的问题。(与基本性能相比而言,基本性能问题认为是方法级别的问 题)
这篇文章将讨论Android系统如何判断一个应用程序处于无响应状态,并为保证应用程序的响应性提供向导。
这篇文章囊括这些主题:
什么引发了ANR?
如何避免ANR?
增强响应灵敏性
1)什么引发了ANR?
在Android里,应用程序的响应性是由Activity Manager和Window Manager系统服务监视的。当它监测到以下情况中的一个时,Android就会针对特定的应用程序显示ANR:
在5秒内没有响应输入的事件(例如,按键按下,屏幕触摸)
BroadcastReceiver在10秒内没有执行完毕
一个ANR对话框显示给用户
2)如何避免ANR?
考虑上面的ANR定义,让我们来研究一下为什么它会在Android应用程序里发生和如何最佳构建应用程序来避免ANR。
Android应用程序通常是运行在一个单独的线程(例如,main)里。这意味着你的应用程序所做的事情如果在主线程里占用了太长的时间的话,就会引发ANR对话框,因为你的应用程序并没有给自己机会来处理输入事件或者Intent广播。
因此,运行在主线程里的任何方法都尽可能少做事情。特别是,Activity应该在它的关键生命周期方法(如onCreate()和 onResume())里尽可能少的去做创建操作。潜在的耗时操作,例如网络或数据库操作,或者高耗时的计算如改变位图尺寸,应该在子线程里(或者以数据 库操作为例,通过异步请求的方式)来完成。然而,不是说你的主线程阻塞在那里等待子线程的完成——也不是调用Thread.wait()或是 Thread.sleep()。替代的方法是,主线程应该为子线程提供一个Handler,以便完成时能够提交给主线程。以这种方式设计你的应用程序,将 能保证你的主线程保持对输入的响应性并能避免由于5秒输入事件的超时引发的ANR对话框。这种做法应该在其它显示UI的线程里效仿,因为它们都受相同的超 时影响。
IntentReceiver 执行时间的特殊限制意味着它应该做:在后台里做小的、琐碎的工作如保存设定或者注册一个Notification。和在主线程里调用的其它方法一样,应用 程序应该避免在BroadcastReceiver里做耗时的操作或计算。但不再是在子线程里做这些任务(因为BroadcastReceiver的生命 周期短),替代的是,如果响应Intent广播需要执行一个耗时的动作的话,应用程序应该启动一个Service。顺便提及一句,你也应该避免在 Intent Receiver里启动一个Activity,因为它会创建一个新的画面,并从当前用户正在运行的程序上抢夺焦点。如果你的应用程序在响应Intent广 播时需要向用户展示什么,你应该使用Notification Manager来实现。
3)增强响应灵敏性
一般来说,在应用程序里,100到200ms是用户能感知阻滞的时间阈值。因此,这里有一些额外的技巧来避免ANR,并有助于让你的应用程序看起来有 响应性.如果你的应用程序为响应用户输入正在后台工作的话,可以显示工作的进度(ProgressBar和ProgressDialog对这种情况来说很 有用)。特别是游戏,在子线程里做移动的计算。如果你的应用程序有一个耗时的初始化过程的话,考虑可以显示一个Splash Screen或者快速显示主画面并异步来填充这些信息。在这两种情况下,你都应该显示正在进行的进度,以免用户认为应用程序被冻结了。
发表评论
-
实现android版 喝优团 引入第三方QQ登录
2014-07-23 12:07 666喝优团 引入第三方QQ登录 -
android版喝优团
2014-07-18 20:30 643喝优团是由大众点评提供数据的手机APP生活消费之一,创 ... -
android论坛网站,里面可以找到很多案例源码
2014-06-03 13:57 78651cto http://mobile.51cto.com/ ... -
Android手机中获取手机号码和运营商信息
2013-09-23 15:05 943来自于http://blog.csdn.net/peijian ... -
Android+JNI调用–文件操作
2013-08-27 18:26 1182这个讲的不错http://www.linuxidc.com/L ... -
Android的NDK开发
2013-08-27 16:01 736http://blog.csdn.net/conowen/ar ... -
Android的NDK开发(5)————Android JNI层实现文件的read、write与seek操作
2013-08-27 14:37 998不错 http://blog.csdn.net/luhuajc ... -
Eclipse NDK 配置
2013-08-23 14:54 693http://www.cnblogs.com/chenjiaj ... -
八款开源 Android 游戏引擎
2013-08-20 18:01 7011、Angle Angle是一款专 ... -
Android连接SQLServer详细教程(数据库+服务器+客户端)
2013-08-15 11:22 1828来源于http://www.6619.net/a/kaifal ... -
Android adb shell 命令
2013-08-12 18:43 677adb 概述 SDK的Tools文件夹下包含着Andro ... -
安卓巴士总结了近百个Android优秀开源项目,覆盖Android开发的每个领域
2013-08-09 20:17 908来源于http://blog.chinaunix.net/ui ... -
android实现显示阳历和农历源码
2013-08-06 21:02 1704来自于http://blog.csdn.net/meshles ... -
android 字体使用自定义的.ttf文件
2013-08-06 20:55 1179这篇文章http://tank03.iteye.com/blo ... -
Android 文件打开方式
2013-08-04 17:56 1647来源于 http://blog.csdn.net/weich_ ... -
详解Android中AsyncTask的使用(简单易懂
2013-08-01 22:06 898from 来此这篇博客。非常不错 -
build.prop详解之修改ROM中默认语言,默认铃声,默认时区,版本信息打造个性rom
2013-07-29 18:29 2879# begin build properties开始设置系统性 ... -
Android系统默认值的设置
2013-07-29 18:28 9851开机图片: android-logo-mask.png ... -
android系统开发设置
2013-07-29 18:27 43601,开机不停震动 手机开机,马达一直震动,应该是uboot正 ... -
ANDROID 隐藏 任务栏 systemui systembar 全屏显示
2013-07-26 14:00 3440ANDROID 隐藏 任务栏 systemui systemb ...
相关推荐
MTK 内部资料介绍ANR 相关 Outline ▪ What is ANR; ▪ ANR key info; ▪ Analyze ANR; ▪ Example; ▪ Need MTK help; ▪ Monkey ANR
2. 报告:系统记录ANR相关信息,包括当前的线程堆栈信息、进程信息、最近的输入事件等。 3. 显示提示:对用户显示一个对话框,告知用户应用无响应,可以选择等待或强制关闭应用。 4. 错误日志:将ANR信息写入系统...
ANR,全称为"Application Not Responding",是Android系统中的一个术语,指的是应用程序无响应。当用户在操作一个应用时,如果该应用在特定时间内(通常为5秒)未处理主线程的消息队列,系统就会检测到这个情况并弹...
在讨论4G网络邻区自配置ANR(Automatic Neighbor Relation)功能优化的过程中,本文首先概述了ANR功能的原理,然后详细介绍了ANR功能设置的具体方面,包括邻区添加和删除的判决条件以及X2链路的建立原则。...
ANR 功能是 Self Organizing Network(自组织网络)的一部分,旨在通过自动发现、自动配置、自动组织等功能,减少运营成本,提高操作效率,尽快提高网络性能和稳定性。 一、ANR 原理概述 ANR(Automatic Neighbor ...
ANR,全称为"Application Not Responding",是Android系统中的一种错误状态,表示应用程序无响应。当用户界面无法在规定的时间内处理输入事件(如点击、滑动等)或者广播接收器在特定时间内未完成操作时,Android...
这包括但不限于应用崩溃日志、系统日志、内存使用情况、线程状态等,开发者可以通过分析这个文件找出导致ANR的具体原因。 在处理ANR问题时,开发者通常会遵循以下步骤: 1. **收集日志**:首先,需要获取到设备上...
* 系统导致 ANR:包括 CPU 被抢占、系统服务无法及时响应、其他应用占用的大量内存等原因。 在分析 ANR 日志时,需要了解 ANR 的产生机制和可能导致 ANR 的原因。只有通过深入分析 ANR 日志,才能找到 ANR 的原因和...
在本压缩包"SR_NE_ANR.zip"中,包含的是一个针对超分辨率问题的ANR(Adaptive Nearest Neighbor Regression)算法的代码实现。 ANR算法是一种基于最近邻插值的超分辨率重建方法,它通过自适应地调整最近邻插值系数...
ANR-WatchDog就像是一个守护进程,持续关注应用的运行状态,一旦发现ANR现象,它可以立即采取行动,如记录日志、发送警报或者执行自定义的错误处理逻辑。 该开源项目的核心功能包括: 1. **实时监控**:ANR-...
ANR 功能相关的标识符包括 Physical Cell Identity(PCI)、Global Cell Identity(GCI)和 E-UTRAN Global Cell Identity(EGCI)。其中,PCI 是 UE 根据无线特性获取的小区标识,GCI 是小区的全球唯一标识,EGCI ...
当Android系统检测到ANR发生时,会在/data/anr/目录下自动生成一个trace文件,其中包含了系统运行时的详细信息,如线程状态、栈跟踪等,这对于诊断问题至关重要。分析trace文件可以帮助我们找出导致ANR的具体原因,...
Android的input系统获取用户输入, 分发给特定的接收者(Framework或应用程序)进行处理, 这个流程涉及到以下一些模块: ... ActivityManagerService.java :ANR 处理. Activity & Views :接收输入事件并处理.
4. **Binder交易信息**:如果ANR与 Binder 通信有关,这里会包含 Binder 交易的详细信息,如等待超时、同步调用等。 5. **系统环境变量**:显示了设备当时的系统环境,如Android版本、设备型号等,这对于判断问题...
标题中的"anr.rar_ANR"可能是指一个名为"anr.rar"的压缩文件,其中包含了与"ANR"(Android应用无响应)问题相关的资料。在Android开发中,ANR是一个常见错误,当应用程序在主线程上执行了阻塞操作,导致用户界面无法...
例如,发生按键响应超时的情况会被记录,同时还会记录CPU的平均负载、ANR发生之前一段时间内的CPU使用率、以及相关的页错误次数等信息。 那么,如何避免ANR的发生呢?开发者可以通过以下方法优化应用性能,从而减少...
ANR(Application Not Responding)是 Android 中的一个错误状态,当应用程序在 5 秒内没有响应输入事件或 BroadcastReceiver 在 10 秒内没有执行完毕时,Android 就会针对特定的应用程序显示 ANR 对话框。...
标题中的“效能智优ANR”可能是指一个针对Android系统优化的工具,因为ANR(Application Not Responding)是Android平台上常见的错误提示,通常当应用响应超时,系统会显示ANR对话框,让用户知道应用运行出现问题。...
Android ANR,全称为"Application Not Responding",是Android操作系统中的一种错误状态,提示用户应用程序无响应。当一个应用程序在主线程上执行的操作超过了5秒钟而没有完成时,系统会认为该应用出现ANR问题,并弹...
- 当ANR发生时,AppErrors首先记录相关信息,包括应用包名、进程ID等。 - 创建一个AppNotRespondingDialog实例,并将其显示在屏幕上。 - 同时,启动一个延时任务,这个任务会在预设的时间(如30秒)后执行。 - 延时...