性能篇(八)无缝设计

释放双眼,带上耳机,听听看~!

       即便您的应用是快速而且响应的,但是某些设计决策仍然可能给用户带来问题——因为和其它应用或对话框的非计划内的交互,无意的数据丢失,不期的阻塞,等。为了避免这些问题,它帮助理解应用运行的上下文和可以影响到应用的系统交互。简而言之,您应该努力开发一款与系统和其它应用无缝交互的应用。

       一个常见的无缝问题是,当应用的后台进程——例如,服务或者广播接收者——弹出对话框来响应某事件时。这视乎是无害的行为,尤其是当在模拟器上单独创建及测试应用时。但是,当您的应用在真机上运行的时候,在您的后台进程显示对话框时,您的应用可能不会拥有用户焦点。这可能最终变成您的应用在活动的应用后面显示对话框,或者可能从当前应用获取焦点,并且在用户正在进行的任何操作前显示对话框(例如拨打电话)。那种行为对您的应用或用户都不起作用。

       为了避免这些问题,您的应用应该使用合适的系统特色来通知用户——【Notification】类。通过使用通知,当事件发生时您的应用可以示意用户,在状态栏上显示一个图标而不是抢占焦点并打扰用户。

      另外一个无缝性问题的例子是,当activity因为没有正确实现onPause()方法以及其它生命周期方法而无意间丢失状态或者用户数据时。或者,如果您的应用暴露数据来给其它应用使用,您应该通过ContentProvider来暴露,而不是(举个例子)通过全世界都能读的原始文件或数据库来这样做。

       这些例子有一个共同点是,它们涉及到系统和其它应用良好地协作。Android系统被设计为将应用视为一种松耦合组件的组合,而不是大块的黑盒子代码。这允许您作为一个开发者将整个系统视为一个这些组件的更大组合。这通过允许您清晰并无缝地集成其它应用来让您受益,并且这样的话您应该设计您自己的代码来反馈这个恩惠。

       本文将讨论常见的无缝性问题以及如何避免它们。

 

不要丢弃数据

       请时刻谨记,Android是一个移动平台。这说起来很明显,但是更要的是记住其它Activity(比如“电话来了”应用)可以在任何时刻弹出来覆盖在您自己的Activity上。这将激发onSaveInstanceState()方法和onPause()方法,并且很有可能会导致您的应用被杀死。

       如果当其它Activity出现时,用户正在您的应用中编辑数据,当您的应用被杀死时将很有可能丢失那些数据。当然,除非首先保存正在进行的工作。“Android方式”的做法是:接收或者编辑输入的Android应用应该重写onSaveInstanceState()方法并且以适当的方式保存它们的状态。当用户重新访问您的应用时,她应该能够取回她的数据。

       一个典型的这种行为的良好使用示例是邮件应用。如果当另外一个应用启动时,用户正在撰写邮件,该应用应该将这封正在进行的邮件作为草稿保存。

 

不要暴露原始数据

       如果您不会穿着内衣在街上走,那么您的数据也不应该。因为这有可能暴露某些类型的应用让全世界读取,这通常不是最好的主意。暴露原始的数据需要其它应用来理解您的数据格式;如果您改变那个格式,您将破坏其它没有进行类似更新的应用。

       “Android方式”是创建一个ContentProvider通过清晰、妥当的、可维护的API来将数据暴露给其它应用。使用ContentProvider非常像插入一个Java语言接口来分开并组件化两个紧耦合的代码片段。这意味着您将可以修改您的内部数据格式,而不用改变ContentProvider暴露的接口,并且这不会影响其它应用。

 

不要打扰用户

       如果用户正在运行一个应用(比如正在通话时使用电话应用),那么这是一个非常安全的赌注,他是故意这样做的。那就是为什么除了直接响应来自当前Activity的用户输入之外,您应该避免生成activity。

       也就是说,不要从正在后台运行的BroadcastReceiver或者Service调用startActivity()。这样做将中断当前应用正在运行的工作,并且导致吵到用户。可能更严重的是,您的Activity可能变成一个“按键强盗”并且收到一些用户正在提供给前一个Activity的输入信息。根据您的应用的所作所为,这可能是一个坏消息。

       您应该使用NotificationManager来设置通知,而不是从后台生成Activity用户界面。这些将会出现在状态栏,并且用户可以在空闲的时候点击它们,来看看您的应用给他们显示了什么。

       (请注意,所有的这些不适用于您自己的Activity已经在前台的场景:在那些场景中,用户希望看到您下一个Activity来响应输入事件。)

 

有很多事情要做?在线程中完成吧

       如果您的应用需要执行一些昂贵或者长时间运行的计算,您可能应该把它们移动到一个线程中。这将阻止可怕的“应用未响应”对话框显示给用户,最终的结果是您的应用火爆地终止了。

       默认情况下,Activity中的所有代码以及它的所有视图都运行在相同的线程中。这也是处理UI事件的同一个线程。例如,当用户按了一个按键,按键按下事件就被添加到该Activity的主线程队列中。事件处理系统需要从队列中取出事件并快速处理它们;如果没有,几秒钟后系统会断定该应用已经被挂起并且为用户杀死它。

       如果您有长时间运行的代码,那么在Activity中内联运行它将会在事件处理线程中运行,从而有效地阻塞事件处理。这将延迟输入处理,并导致ANR对话框。为了避免这种现象,将计算移动到子线程中。【为响应而设计】文档中会讨论如何做。

 

不要过度加载一个单独的activity屏幕

       所有值得使用的应用可能有多个不同的屏幕。当为您的UI设计屏幕时,确保使用多个Activity对象实例。

       根据您开发的背景,您可能解释Activity为类似于Java Applet的东西,因为它是您应用的入口点。但是,那并不完全正确:Applet子类是Java Applet唯一的入口点,但是Activity应该被认为是可能的进入应用的几个入口点之一。您“main”Activity和任何其它Activity之间您可能拥有的唯一差别是,“main”Activity碰巧是唯一一个对AndroidManifest.xml文件中的“android.intent.action.MAIN”行动表达过兴趣的Activity。

       所以,当设计应用时,将应用看成是Activity对象的组合。从长远看,这将会让您的代码更加具有可维护性,并且作为一个很好的副作用,它与Android的应用历史以及“回退栈”模式配合得非常好。

 

继承系统主题

       当涉及到用户接口的外观和感觉时,重要的是将它们很好地融合在一起。用户被那些与他们所期望的用户接口截然不同的应用弄得很烦躁。当设计您的UI时,您应该尽可能尝试避免滚动您的界面。相反,使用主题。您可以重写或者继承那些您需要的主题部分,但至少您正在从和其他应用相同的UI基础启动。更多详情,请查阅【类型和主题】。

 

设计您的UI来适配多屏幕分辨率

       不同的Android驱动设备将支持不同的屏幕分辨率。有一些将甚至可能在运行中改变分辨率,比如通过切换到横屏模式。重要的是确保您的布局和图片在不同的设备屏幕上足够灵活,以正确显示。

       幸运的是,这非常容易实现。简单来说,您必须要做的是为主要分辨率提供不同的图片版本(如果您使用任何一个),并且设计您的布局来适配不同的尺寸。(例如,避免使用硬编码位置并且使用相对布局。)如果您做了很多,系统会处理剩下的,并且您的应用在任何设备上都看起来很不错。

     

假设网速慢

        Android设备将会提供各种不同的网络连接选项。所有的这些选项将拥有一些数据访问规定,虽然有些将会比其它的快。可是,最小的公分母是GPRA,这是一种用于GSM网络的非3G数据服务。即使是支持3G的设备也将花费很多时间在非3G网络上,所以在未来很长一段时间缓慢的网络将仍然是一个事实。  

       那就是为什么您应该总是编写您的应用来最小化网络访问和带宽。您不能假设网络是很快的,所以您应该总是为网速变慢做好计划。如果您的用户碰巧在更快的网络,那是很棒的——他们的用户体验将只会提升。不过,您希望避免相反的情况:基于任何给定的时刻用户所在的位置,部分时间可以使用,但剩余时间却非常慢的应用,可能是不受欢迎的。

       这里有一个潜在的问题是,如果您正在使用模拟器,将很容易掉进这个陷阱,因为模拟器使用的是您的桌面电脑网络连接。那几乎可以确信比蜂窝网络快很多,所以您将需要更改模拟器上用来模拟更慢的网络速度的设置。当启动模拟器时,您可以在AndroidStudio中通过AVD Manager或者通过【命令行选项】来做这件事。

 

不要假设触摸屏或者键盘

       Android将会支持多种遥控器形式的因素。那是一种很奇特的说法,某些Android设备将拥有完整的“QWERTY”的键盘,然后其他的设备将拥有40按键,12按键,或者甚至其它按键配置。相似地,有些设备将拥有触摸屏,但是很多却没有。

       当构建您的应用时,请记住那些。不用假设特别的键盘布局——当然,除非您确实热衷于限制您的应用以至于让它只能在那些设备上使用。

 

节省设备电池

       如果经常被插到墙里,那么移动设备就不那么移动了。移动设备是电池驱动的,并且让电池一次充电后延续的时间越长,所有人就越开心——尤其是用户。电池电量的两个最大消费者是处理器和无线通信;那就是为什么尽可能编写您的应用来做尽可能少的工作,并且尽可能少地使用网络是很重要的。

       最小化您应用使用的处理器时间实际上来源于【编写高效的代码】。为了最小化来自使用无线电通信的电量流失,请确保优雅地处理错误条件,并且只取您所需要的。例如,如果一次失败了,不要经常重试网络操作。如果它失败了一次,极有可能是因为用户没有接收信号,所以如果马上尝试,可能将要再次失败;所有您将做的都是浪费电量。

       用户时非常明智的:如果您的程序是非常耗电的,您可以指望他们注意到。在那个点上,您唯一能确信的事情是,您的程序安装时间将不会很长了。

给TA打赏
共{{data.count}}人
人已打赏
随笔日记

Tomcat 容器的设计和实现

2020-11-9 4:40:57

随笔日记

记一次失败的官网项目

2020-11-9 4:40:59

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索