前言
SDK开发和app开发的区别:
从用户角度来讲:
app开发主要面向的是普通的用户需求,SDK开发面向的是开发人员。
从技术角度来讲:
app开发更多的只是UI层面、基于数据流的技术实现;而SDK开发可能要涉及更多的复杂的需求、更多底层的技术实现。
相关概念
什么是SDK
SDK,Software Development Kit,软件开发工具包,通常是为辅助开发某类软件而编写的特定软件包,框架集合等,SDK一般包含相关文档,范例和工具。
SDK可以分为系统SDK和应用SDK,所谓的系统SDK是为特定的软件包,软件框架,硬件平台,操作系统等所使用的开发工具集合。而应用SDK则是基于系统SDK开发的独立于具体业务而具有特定功能的集合。
比如在进行Android应用开发时,我们使用Google提供的系统SDK(Android SDK),而我们经常使用的友盟SDK,极光SDK则是基于系统SDK开发的。
什么是Library
Library即库,通常是一组或者几组类的集合,通常是应用中某些功能的具体实现或者对系统已有功能的增强或补充。对Android开发者而言,最常见的是Support Library,另外就是我们经常使用各种网络请求库(OkHttp,Vooley),数据库操作,图片加载库(Glide,ImageLoader)等。
什么是Framework
Framework,即框架,通常是系统或者应用的骨架,它表现为一组抽象的构建及构件实例间交互的方法。因此,可以认为Framework规定了应用的体系结构,阐明了整体设计,写作构件之间的依赖关系以及控件流程。
注意:这里的Framework并不完全等同于Android Framework框架,可以认为Android Framework中体现了Framework的思想,并进行了实现。
什么是API
API是Application Programming Interface,又称为应用编程接口,是软件系统不同组成部分衔接的约定。简单来说,API就是我们常见和编写的方法或函数。
小结:
SDK,Library,Framework,API四者之间的关联(SDK的主要构成)
SDK主要包含Framework,API及Library的三部分。Framework定义了SDK整体的可重用设计,规定了SDK各功能模块的职责以及依赖关系。其中功能模块体现为Library。模块之间的内部通信及SDK外部通信(SDK对外提供服务的接口),则通过API进行。
另外完整的SDK还应该包含大量的示例和其他工具,比如在Android SDK的tools目录下提供了大量的辅助开发工具。
对我们而言,大部分情况下是为某种具体的业务需求开发对应的SDK,以便作为第三方提供给其他需求方使用,比如百度推送的SDK主要实现消息推送功能,需求方只需要集成百度推送的SDK便可以使自己应用具备推送功能。
二、SDK实现目标
任何应用包括SDK都应具备:简洁易用,稳定,高效
简洁易用
一个好的产品对第三方使用者而言应该是简洁易用,不应该让使用者花费太长时间学习。SDK不应该对宿主应用有过多的代码侵入,也不应该有复杂频繁的接入工作。比如当开发者需要使用SDK的服务时,只需要在自己的代码中新增一行即可。常见的SDK初始化如下:
public class Ad{
@TargetApi(9)
public synchronized static void init(Context context,SdkParams params){
...
}
}
当我们需要使用该SDK的服务时,通过一行代码即可启用:Ad.init(this,params)
稳定
站在SDK使用者角度来看,我们期望第三方的SDK服务应该是稳定高效的,体现在提供稳定可靠的服务,在不影响宿主稳定性的前提下足够的高效,这就要求我们SDK设计者在设计并实现SDK时要尽可能的做到以下几点:
对外提供稳定的API.SDK的API一旦确定,如无非常严重情况不可更改.作为提供服务方,发生API变更所带来的变更成本非常大.
对外提供稳定的业务.在稳定的API后,必须要有稳定的业务来支撑.
SDK运行时的稳定,作为服务提供方,我们必须确保SDK自身运行的稳定,并且保证接入方不会因为我们的SDK产生不稳定的情况.
版本稳定更新.和面向普通用户的应用相比,SDK版本的迭代是非常缓慢的.并且需要尽可能的对开发者屏蔽迭代过程,以免给开发者带来不必要的适配开销.
高效
无论是普通的应用开发还是SDK开发,都应该考虑到性能问题,SDK设计者应该着重考虑以下问题:
更少的内存占用.在不使用多进程的情况下,SDK服务和宿主程序运行在同一进程中,这种情况下必须要求限制SDK内存的占用,不能因为说因为我们SDK占用太多的内存资源,导致应用的存活时间变短.
更少的内存抖动.在占用更少内存的前提下,SDK设计者必须刻意的减少反复GC造成的内存抖动问题.
更少的电量消耗.尽管很多时候无法对电量消耗做一个很好的权衡,但是仍然有一些可以参考的做法,比如减少使用耗电模块的时间.比如在使用定位服务时,不要求非常高的精度下优先使用网络定位而不是GPS定位.
更少的流量消耗.
三、SDK整体架构设计
SDK的架构实现决定了SDK后续的维护难度,因此有必要在此对SDK整体架构中的一些点做些简单的说明.
模块化开发
根据单一职责将系统拆分为不同的小模块,每个模块保持相对独立。
模块之间通过协议或接口通信,以减少相互之间的依赖耦合.模块内部按照设计的几大原则进行实现,以保证模块本身可以灵活实现
对于现代开发而言,模块化是常用的手段,从宏观角度来看,模块是系统最小的组成单元.
组件化开发
组件是对逻辑的封装,并具备单个可移植性。比如可以把日志记录做成一个组件,之后它可以应用在不同的项目中。对于Android开发者而言,Android提供的每个UI控件同样也是组件,比如Button,TextView等。
概念:组件化就是将整个项目划分成多个模块,几个模块或者单个模块作为一个组件,开发过程中我们可以对每个组件进行并行开发,最后发布时通过依赖将组件合并成完整的应用。
为什么要使用组件化呢?
随着android的逐渐成熟,现在的app业务越来越复杂,与此同时,android工程也变得日益庞大,代码行数十几万已经是常态,此时有几个问题便会凸显出来:
工程任何一点改动都会造成整个工程的重新编译.早期在没有进行组件化的时候,需要很长的编译时间。
整个工程中充斥的大量重复或者冗余的子模块,业务耦合度非常高,牵一发而动全身.
很难进行协作开发和代码合并
不方便测试.高度耦合的业务和模块导致无法下手进行测试。
通过引入组件化,上面遇到的问题便可迎刃而解.在SDK当中,根据实际情况对其进行组件化,比如我们将分享功能组件化,可以轻松的支持多种渠道的分享,在需要更新分享功能时,可以对其进行单独的编译和测试.
通过组件化,我们也可以轻松的实现SDK的定制功能,通过编写编译脚本,我们可以决定哪些组件被依赖,最终合并到完整的应用当中.比如友盟中的提供的可定制分享组件的原理就是如此.
插件化开发
在SDK中为什么使用插件化呢?SDK不同于普通应用,不能频繁的进行更新,以免让开发者觉得SDK不稳定或者让开发者频繁的集成.SDK看起来变化较慢,实则变化频繁.就以以前做的广告SDK而言,有时候经常需要对某类机型进行数据采集或者及时更新反作弊模块,在没有使用插件化之前,解决该问题是非常麻烦的.但是在我们利用插件化之后,解决该问题就变得非常容易:我们将SDK整体划分为两部分:宿主和插件.宿主只向开发者提供必要的服务接口,并提供了自定义插件加载器.而核心的逻辑则是存在于插件中.当需要采集数据的时候,只需要由开发人员开发好数据采集插件并下发到指定设备即可;当需要修复SDK缺陷时,同样也只需要下发新的插件包即可.
通过在SDK使用插件化方案,可以有效的对开发者屏蔽手动更新的过程.宿主相对稳定,一旦确定,一般不会变动,而后续的业务变化则只需要通过更新插件来支撑.
除了上面谈到的利用插件化解决动态更新之外,通过将整个工程分为宿主和插件可以实现宿主的并行开发和分开编译,并且能有效的解决方法数65535的限制.
SDK初始化
和应用开发不同,很多情况下SDK没有自身的上下文Context,而必须要借助应用提供.SDK初始化的常见做法:Ad.init(Context context,AdParams params),我们往往推荐开发者在应用Application组件中的onCreate()中去掉用该方法,这就意味着该初始化过程是同步的,假如SDK本身初始化时间较长,就会影响应用的启动速度.
在这种情况下,作为SDK的设计者必须着手解决该问题.通常将SDK服务进一步划分成核心服务和辅助服务,之后通过并行初始化和延迟初始化的手段来减少SDK初始化耗时.曾经在我所负责的广告SDK中,有开发者反馈我们的SDK启动较慢,通过对整个SDK启动流程进行分析后,我们将插件加载服务和云控服务并行初始化,而对于像日志服务则采用延迟初始化,通过该手段有效的减少了初始化耗时
云更新控件
云控服务作为一种服务端控制客户端的手段在SDK中开发中非常重要,现在的SDK开发可以不支持插件化,但是必须要提供云控服务,以便让服务端能控制SDK,比如在不需要进行数据采集的时候,可以通过云控服务关闭SDK采集功能,在需要的时候在将其打开.
对本身是基于插件化开发的SDK而言,云控服务更是不可或缺.
从实现的角度而言,云控服务分为服务端主动和客户端主动.服务端主动是指服务端会将最新的云控开关的信息推送到SDK,而客户端主动则是SDK在进行操作之前会首先请求云控信息.对有推送开发经营的同学而言,这非常容易理解,就是像是为了实现消息推送功能,我们可以通过客户端轮询也可以通过服务端保持长连接进行消息推送一样.
以上是根据我的一些理解,做的总结分享,旨在抛砖引玉,希望有更多的志同道合的朋友一起讨论学习,共同进步!
参考文献:
http://blog.csdn.net/dd864140130/article/details/53558011