查看原文
其他

从iOSer的角度看Android开发

The following article is from 非典型程序熊 Author klarm

前言

为什么iOS开发者需要懂Android开发?

“大前端时代,完全不懂Android的iOS开发者不是好的前端工程师。”

1、 从个人技能广度、视野的角度

作为一个开发人员,可以把某个平台的开发作为自己的主要目标,但是不能把自己局限在现有平台,在某个平台达到一定的深度之后,需要扩展广度和视野,这样才能有持续提升的空间(其实更大一点讲,绝不仅仅局限在技术方面,这当然是一个更大的话题),偶尔跳出现有平台的局限,你会看到,其实那么多平台、那么多框架、概念、技术,其实他们的差异没有想象的那么大,共性远大于差异;

2、从大前端时代的角度

在当前的大前端时代,各类跨端框架层出不穷,从前几年的RN到小程序,再到最近热度越来越高的Flutter,乃至于国内各家大厂自己造的各种轮子,而且这里的跨端已经不再局限于移动双端,甚至纳入了H5甚至是桌面平台(如Electron、Taro等),从开发者最直观的感受来看,就是脚本类 to native的开发逐步变得强势。各大厂纷纷在主营业务上开始使用这些技术和框架,并且似乎都没有回头的意思,尽管从微观看,各类方案都存在一些这样那样的欠缺,如体验、成熟度、工具链、社区等等,但是这不会影响趋势,只是快慢而已。故而,可以认为,在大前端时代,一个合格的前端工程师应该具备的技术栈是:脚本(js居多)+ iOS/Android,与最近几年充满争议的全栈工程师的概念相比,这条道路其实更具备可操作性。

所以作为一个专注于iOS平台的开发者,不管是从个人发展还是从跟上产业步伐的角度,具备基本的Android开发技能是十分必要的。

1、目标

Android平台的知识纷繁复杂,本文不需要(实际也不可能)覆盖所有的主题。

其实,一方面,我们不需要全部重新学习,很多概念都是类似的,可以进行类比;另一方面整体上也是有章可循的,这里的“章”是什么呢?就是Android系统的设计思想。综合上面的考虑,可以从三个目标着手:

a) 理解Android设计思想

理解了其设计思想,才能明白为什么要这样设计,为什么要引入这种机制,不会过早陷入各种细节的迷雾,碰到各类问题也会有大致的解决思路。

b) 知晓Android组件原理

在理解Android平台设计思想的基础上,知晓常用组件的原理,以及iOS平台上类比的概念。

c) 思考、总结、借鉴

自己的总结、思考,以及是否可以借鉴到平时的工作中。 

2、Android平台的设计思想

Android之父Andy Rubin有过一句话:“希望Android能像Facebook那样可以使用不同的应用中的功能模块,通过现有的模块像搭积木一样方便地构建一个应用”。 这是从产品或者功能层面描述的,如果从更技术一点的角度,可以有另一句话:“Android是一个为组件化而搭建的平台,它被设计为高度组件化、可复用的,参考了所谓Mashup的概念。”


这里有2个关键词:组件化、Mashup。


对于软件开发人员来讲,组件是平时用到的最多的词之一,谈到组件,我们会想到很多名词,比如:方法、类型、对象、库、包…等等。从广义上来讲,这些都可以某种程度上视为组件,那么怎么来理解组件呢?说说我的理解:

a) 隔离

这里的隔离包括类型、功能、概念等的隔离,为什么要隔离呢?因为人只能在同一时间处理一定范围内有限的、明确的事情,编程也不例外。所以隔离的本质就是处理复杂度。组件通过隔离降低了整体和局部的复杂度,使之更容易控制和处理。

b) 协作

为了合作完成功能,组件不能是完全与外界没有交流的黑盒子,所以还需要协作。

所以组件设计的关键是处理好隔离和协作之间的关系。很多人会说,你说的组件的概念我们也很熟悉了,不稀奇,那么Android的组件有哪些特点呢?这涉及到第二个关键词:Mashup

Mashup最早是一个音乐领域的概念,后来被引入到技术领域,指的是指的是Web开发中将多个Web站点的数据、页面、功能汇合在一起,构建新的Web服务。总结起来Mashup其实就是独立完整功能的聚合。

传统应用程序:有清晰的应用边界,应用内部,功能组件划分自由;Android应用:只有清晰的组件边界,不再有明确的应用边界和进程边界。如下图所示:


高度组件化衍生出Manifest、基于Intent的通信、组件生命周期、进程托管、Task等其它概念。

在Mashup模式下,每个组件的功能都可以被充分复用,应用被完全解构。来自不同应用的组件可以有机结合在一起,共同完成功能。

3、组件介绍

A. Manifest

B. 四大基本组件

C. Intent

D. Widget & layout


3.1 Manifest

Manifest负责权限配置、环境配置、组件清单及配置、依赖库配置、其他各种配置,总之就是一个xml格式的配置表。我们很容易将它类比为iOS中的plist。

3.2 Activity/Fragment

Activity是Android中与UI相关的组件,主要负责构造界面、菜单、对话框,处理交互。Activity一般是通过xml布局文件来构造的,IDE提供了布局文件可视化编辑预览的功能。实现一个Activity有4个要点:

a) 直接或者间接从Activity基类继承

b) 在OnCreate中通过布局文件创建对应的视图

c) 通过观察者模式设置事件响应的处理

d) 为了让系统知道这个Activity的存在,我们还需要在配置文件中配置这个Activity。


Fragment在Android 3.0之后引入,可以看成是Activity的片段,由Activity管理,依赖Activity存在。Fragment的引入有利于模块化开发,代码复用,因为同一个Fragment可以被多个Activity嵌套,而且Fragment可以像普通对象创建、控制、替换,由于可控性。

Fragment可以类比为iOS中的child ViewController、content ViewController。

Activity和Fragment都有一系列的生命周期相关回调方法,这也可以与ViewController中的viewDidLoad、viewWillDisappear等类比,如:

onCreateView->viewDidLoad

onResume->viewDidAppear

onPause->viewWillDisappear

onStop-> viewDidDisappear


3.3 Service

从功能概念方面,Service类似于传统桌面平台服务,它在后台默默提供功能,进行调度和统筹。对于一般的iOS应用而言,其实没有真正意义上的后台服务,系统仅仅是提供一段时间供App完成未完成的工作。

3.4 Broadcast Receiver

Broadcast Receiver监听系统或者系统中其它应用发出的事件,并作出反应,与其它应用交互。从消息监听的角度来讲,类似于iOS中的NotificationCenter,从与其它App交互的角度来讲,勉强可以靠上的是OpenUrl?(其实除了url之外,还有一些非主流的App间的通信方式,比如keychain、剪贴板等)

3.5 Content Provider

Content Provider不包含特定的功能逻辑,而是负责为应用提供数据访问接口,它是为了帮助应用共享数据而设计的。iOS这块系统原生支持的方法不多:keychain、剪贴板、以及iOS8之后引入的app group。整体上来讲,iOS中没有和Content Provider对应的概念。

3.6 组件总结

Activity 表(外观)

Service 里 (后台服务)

Broadcast Receiver 耳朵(收听消息)

Content Provider 嘴巴 (输出内容)

与iOS类比:

Activity->ViewController

Service->Background mode?

Broadcast Receiver->NotificationCenter、OpenUrl

Content Provider->None


组件的三要素:组件+配置+连接,前两点已经有了对应的概念(组件与Manifest),那么组件之间的连接怎么表达呢?这就涉及到所谓基于意图(Intent)的通信。什么意思呢?直观理解就好了,我要做某件事情,那么我将我的意图描述清楚,交给某个人,他帮我做就行了,这里的某个人是谁呢?就是系统。

具体来说,引入系统组件管理服务作为连接组件的管理者,该服务通过配置了解系统中每个组件的类别和功能,帮助调用者寻找符合其需求的组件。

这其实就是所谓的Mediator模式,也称中介者模式。那么这种模式的好处在哪里呢?好处就在中介双方的对象不需要显式地互相引用,从而使其耦合变得松散,其实就是依赖下沉。

那么系统怎么知道哪个组件有什么能力呢?这是通过所谓的Intent Filter来描述的。Intent Filter是各个组件描述其功能的,通过该信息系统的组件管理服务就可以知道各个组件具备的能力、能够处理的请求。

有了调用者的Intent和接收者的Intent Filter,系统可以将两者进行匹配,如果匹配成功(有一套匹配算法),系统作为中介者将接收者调起。


4、Widget & layout

对于每个平台来说,UI系统都是一个非常重要的方面。尤其是对于移动平台的开发者来说,UI相关开发占据平时工作中很大一部分。与其他平台类似,Android也抽象出View的概念,作为UI的基本单元,从View派生出一套庞大的控件体系,与iOS平台不同的是,Android中的View分为View和ViewGroup两类,前者是按钮、图片、文本等基本控件,后者是一些排版容器,支持各类排版方式,如线性排版、相对排版、绝对排版、网格排版、栈式排版等。


5、总结

Android应用是高度组件化解构的,即:

Android应用 = 组件 + 组件


组件的三要素:

组件 = 组件 + 配置 + 连接


组件:四大基本组件


配置:Manifest


连接:Intent


组件之间的交互是以系统作为中介进行的,组件不会直接进行通信。系统如何获取充当中介所需要的信息呢?来自配置文件(Manifest)。

从暴露给开发者的风格上来讲,iOS可以用“外紧内松”来形容,外部限制颇多,但是内部有很大自由发挥的空间;Android则恰恰相反,可以用“外松内紧,戴着镣铐跳舞”来形容。从组件分隔的角度来看,可以视为:一体化 VS 相对松散的组合 or 联邦 VS 邦联的关系。

为什么两者形成了上述不同风格呢?iOS的重点是:隔离、安全;Android的重点是:开放、复用、共享。这导致了不同设计策略,架构的本质是管理复杂性(复杂性就在那里、不同的目的、侧重点不同,设计不同,所以一定要想清楚自己要做什么),谁对谁错,其实都是对的,因为他们都满足了其设计目标。当然其实目前两个平台也在不断靠拢,iOS也在逐步增加共享、开放的支持,至于Android,Google也在逐步加强控制(当然国内还有点特殊,各家的UI or OS还会存在较长的时间)。

本文从iOS开发者的角度提供了Android的一些入门知识,总结过程中,采用的风格是忽略细节、力求有整体概念,通过与iOS平台的相似概念类比,充分利用已有开发经验,希望能消除隔离感,完成从0到1的过程。当然最好的学习方法肯定是选择一个规模适中的应用,完成其向另一个平台的转换。



也许你还想看

堡垒机:爱奇艺海量服务器安全运维平台的建设

干货|爱奇艺直播 - 春晚直播业务API架构


扫一扫下方二维码,更多精彩内容陪伴你!

爱奇艺技术产品团队

简单想,简单做


    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存