通过非Android开发人员的眼光了解Android体系结构的功能

最近,我们已经完全重新设计了适用于Android的Pyrus应用。 该应用程序的第一个版本已在Android 2.2下运行。 拒绝支持4.1以下的Android,我们得以偿还了累积的技术债务并大大简化了源代码。 是的,我们失去了一部分用户(少于1%),但另一方面,我们节省了开发人员修复罕见bug的时间。 我们将能够将其投资于所有现有和新用户的功能开发中。 从长远来看,这更为重要。

在这里,我们分享了一些经验,这些经验对于那些正在考虑开始开发Android平台的人可能有用。

Android吸引了良好的开发工具,使用常规语法的久经考验的语言(Java)和大量用户。 但是,在Android上创建方便的应用程序很困难:尽管开发了API,但经常会发生没有具有适当行为的现成组件。 您必须放弃UX设计器的想法,或者同意依赖第三方库,或者自己编写。 并非所有Android架构解决方案都成功了,这也增加了代码量,却没有明显的好处。

死灰复燃


Android中的界面基于Activity。 这是一个通常占据设备整个屏幕的容器,其中包含其他小部件,并且它接收有关用户交互的事件。

当用户激活应用程序时,活动中将引发onResume事件。 按下“主页”按钮-活动消失了,但是在此之前,他收到了onPause事件。 到目前为止,一切都是合乎逻辑的。 用户将设备屏幕旋转90度会发生什么? 您永远不会猜到:操作系统杀死了Activity并重新创建! 卸载活动时,该活动包含的所有组件都会被删除。 这意味着您必须编写特殊的代码,以将小部件的状态保存在“活动”中(滚动位置,选定的文本片段,复选框的状态),并在重新创建父级后将其还原。 Android为您完成了部分工作,但并非全部。

很难理解是什么促使建筑师做出这样的决定。 后来,有人认为它看起来有些丑陋,并添加了相同的参数,从而抑制了系统的默认行为。 现在,代替重新创建Activity,OS可以调用特殊的onConfigurationChanged方法。 这种“解决方案”看起来像是一个肮脏的hack,只会加剧问题,因为Android文档 “该技术应被认为是一种极端手段,不建议大多数应用程序使用”。

碎片碎片


最初,Android OS是为手机创建的。 随着平板电脑的问世,Android团队正确地决定,由于手机屏幕较小而以前因不同的活动而间隔开的那些界面元素现在可以在平板电脑的大屏幕上共存。 (示例:电话中的字母列表和电子邮件位于两个不同的活动中,而在平板电脑上,它们一起共享一个屏幕。)是的,麻烦是:多个活动无法通过设计与用户同时进行交互。 因此,需要另一种重用组件的机制,并且找到了一种解决方案:出现了碎片(碎片)。

根据定义 ,片段代表活动中的行为或用户界面的一部分。 一切都清楚了。 但是,在使用片段的说明中,我们找到了“添加没有用户界面的片段”部分。 什么啊 事实证明,片段可能没有自己的渲染窗口!

但是打开屏幕时碎片会怎样? Android开发人员考虑了这一点-当您重新创建活动时,其所有片段也会自动重新创建。 但是,经过仔细考虑,该片段具有“ setRetainInstance”方法,如果调用它,则该片段将不会在转弯期间删除和还原。

苗条和一致的这个概念不能被称为。

异步运行


事件处理线程不能通过长时间的操作来阻止,因此与磁盘和网络的数据交换应该在其他线程中异步进行。 Android提供了多达四种异步操作机制:AsyncTask,Service,IntentService,Thread。 鼓励开发人员找出最适合他们使用的一种。 该选择并非无关紧要:例如,如果应用程序启动了AsyncTask,并且用户在执行过程中打开了屏幕,则工作完成后,AsyncTask将无法找到新的(在转弯后创建的)Activity。 四种机制都没有实现简单的逻辑:如果用户在不等待第一个异步结果的情况下启动了第二个异步过程,然后第一个异步过程仍提前结束,则可以忽略并不在UI中反映其结果。

很明显,许多库的外观-用于在Android应用程序内部组织异步工作的数据总线。

OOM之后重新启动应用程序


如果Android用完了可用内存,则操作系统可以完成任何过程。 当用户将来激活该应用程序时,系统将尝试恢复其状态。 从理论上讲,这对于开发人员应该是不可见的(如果他在所有组件中都实现了onSaveInstanceState方法):系统本身将重新创建Activity堆栈,就像在强制停止期间一样。 但是,如果初始化需要时间(例如,从磁盘或从网络加载缓存),则向用户显示等待指示符将是正确的。 事实证明,在创建活动时,您仍然需要监视“冷启动”并手动执行初始化。 更不用说重新启动时,不会还原Thread和AsyncTask。

在实践中耗尽内存的可能性有多大? 通常,这种情况在处理高分辨率图像时发生。 例如,一个2048x1536图片在位图对象的内存中占用12Mb。 应用程序可用的内存量取决于特定的设备型号,有时很小(64Mb或128Mb)。 由于8.0之前的所有版本的Android中的垃圾收集器都没有压缩,因此即使您有100Mb的可用内存,但它却被分成10Mb的块,因此尝试为此类图片分配内存会导致应用程序崩溃。

永恒垃圾回收


一旦我们的用户注意到滚动长列表时,应用程序“滞后”-每2-3秒,动画就会停止片刻(200-300毫秒),然后继续播放。 分析表明,可疑垃圾回收经常在应用程序中启动。 事实证明,在这种情况下,标准的HashMap类(用于通过其ID获取Java对象)效率低下:我们需要为每个键创建一个包装对象,该对象是整数(int)。 因此,增加内存分配的数量没有任何好处。 解决方案是切换到特殊的SparseArray容器(仅在Android中可用,而在标准Java平台中不可用),这立即减轻了垃圾收集器的压力。

您问动画的滞后与它有什么关系? 事实是,Android中的垃圾收集器在其运行期间停止了所有线程,包括渲染所涉及的主线程。 在从5.0开始的Android版本中,使用了另一个虚拟机(ART代替了Dalvik)和不同的垃圾收集算法,该算法越来越少地暂停动画。 (您可以在此处阅读有关比较垃圾收集时间的信息 。)

查看文件


如果要在应用程序中插入文档预览,您将不得不失望:在Android中,没有可显示Word,Excel,Powerpoint文件的内置组件。 更不用说ZIP存档或PDF文档。 出路? 强制用户安装第三方应用程序以查看每种类型的文件或使用WebView组件(实际上是浏览器)。 在这两种情况下,当用户对文件进行录音时,都会启动外部应用程序,并且某些情况根本无法实现,例如,图像提要:没有简单的方法将WebView集成到标准ViewPager中。

接下来是什么


一些研究声称, Android开发复杂性相对较高 。 我们的经验表明,有能力的开发人员很容易习惯该平台的功能。 尽管今天的Android是世界上最受欢迎的移动操作系统,但在5-10年内情况可能会发生根本变化。

近年来,Google一直在秘密开发新的Fuchsia OC ,它具有根本不同的安全模型(与现代OS相比)。 它将可能使用Dart作为主要的编程语言,并使用Flutter框架作为创建应用程序的主要方式。 有传言说, 紫红色可以在所有设备上取代Android和ChromeOS 。 如果Google这样做,该公司可能会为Android编写的应用程序提供本机支持(就像Microsoft从DOS切换到Windows时所做的那样)。 因此,到目前为止,您不必担心并且会继续积累Android方面的专业知识。 对于那些希望展望未来的人,您可以在这里下载Flutter并使用它。

Source: https://habr.com/ru/post/zh-CN416689/


All Articles