说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

从友盟微社区看Android第三方SDK架构实践

HTML文档下载 WORD文档下载 PDF文档下载
第三方SDK的开发需要考虑很多因素,比如稳定性、灵活性等,并且还要做到能让开发者能自由定制UI层、替换子系统。本文以友盟微社区为例,详细讲解了在开发SDK时架构方面的设计理念。

开发Android第三方SDK说难不难,但说简单也不简单,要开发一个给很多人使用的第三方SDK,如何在保证稳定性的同时,增强SDK的灵活性,让开发者能自由定制UI层、替换子系统,这是一个值得思考的问题。为了解决这个问题,开发第三方SDK必须要有良好的应用架构。本文就分享一下我在开发友盟微社区SDK时在架构方面的一些想法。

友盟的微社区是一款帮助开发者在应用中快速搭建一个社区(类似于新浪微博、朋友圈),目前正在内测当中。

技术架构

从项目结构上来说,友盟微社区SDK可以简单分为如下三层。

  • UI层(开源)。UI层对外开放,目的是让用户能够定制微社区的UI效果,使微社区SDK能够很自然的融入到用户的App中。
  • 业务逻辑层。业务逻辑层会通过一个统一的接口向UI层提供数据请求等功能,比如获取缓存的feed、好友列表等,因此业务逻辑层对于用户来说是一个数据操作接口,通过这个接口用户能够与SDK核心层进行一些数据方面的操作。
  • 核心层。核心层则包含了友盟SDK的核心系统抽象,比如账户系统、推送、数据库、网络操作等,这一层对外封闭,用户可以通过一些接口与核心层进行交互。而核心层定义的抽象使得用户可以很方便的实现定制化,即自己实现抽象接口,然后将具体的实现注入到微社区中,从而使自己的子系统替换掉微社区中的默认实现。

如图1所示,SDK层次非常分明,通过这三个层次的隔离,使得用户既可以自定义最外层的UI效果,也对外隐藏了业务逻辑层、核心层的实现细节。而核心层定义的子系统抽象,使得用户可以注入自己的实现,保证了整个微社区SDK的灵活性、扩展性。

图1 洋葱结构图


简单来说,就是用户在UI层通过逻辑层暴露的通用接口来操作SDK,从封闭的核心系统中获取、存储数据以及其他的相关操作。层次结构如图2所示。

图2 层次结构图

图1、图2都显示了SDK是通过不同的层次来分离职责,是一个较为典型的架构形式。对于用户来说,最关心的莫过于可定制化。UI层开放源码,自然可以通过修改代码来实现。其他的定制化用户就需要依赖注入来实现。微社区SDK内部依赖于抽象,而不依赖于具体实现,并且用户可以注入具体实现。也就是说用户可以根据我们的抽象接口实现自己的子系统,然后注入到SDK内部,SDK此时就会使用用户注入的实现,这样就达到了子系统替换的效果,也就是我们说的定制化。

友盟微社区的定制化

如何满足定制化?

那么如何来实现定制化呢?友盟微社区SDK内部定义了一些抽象,比如Loginable、Pushable、ImageLoader来分别代表登录系统接口、推送接口、图片加载接口,每种接口都有一个SDKManager来进行管理。比如管理登录子系统的就是LoginSDKManager,用户可以往这个Manager里面添加、移除具体的登录系统实现,然后通过useThis函数来指定使用某个具体的实现(SDK Manager里面可能有多个实现)。结构图如图3所示。


图3  LoginSDKManager功能

SDK Manager是一个泛型类,类型T就代表了接口类型,比如上述的Loginable等。通过泛型我们就可以将这些通用的添加、移除实现等操作抽象化,避免重复代码。代码如下所示:

public abstract class SDKManager<T> {

  //泛型Map

 private Map<String, T> mImplMap = new HashMap<String, T>();

 // 要使用的实现的key

 private String mCurrentKey = "";

 public void addImpl(String key, T impl) {

 mImplMap.put(mCurrentKey, impl);

  }

 public void removeImpl(String key) {

 mImplMap.remove(mCurrentKey);

  }

 public void useThis(String key) {

 mCurrentKey = key;

  }

 public T getCurrentImpl() {

 return mImplMap.get(mCurrentKey);

  }

}

代码很简单,就是在SDK Manager内部维护了一个Map,key是用户为这个实现指定的一个字符串值,value就是具体的实现。用户可以通过这个key来移除实现,更常用的是我们需要调用useThis(String key)接口来指定使用某个具体的实现。 

我们并没有直接使用SDKManager,因为它是一个抽象泛型类,因此我们定义了一些子类来对不同的实现进行管理,这些子类都是单例类,例如LoginSDKManager,代码如下所示。

public final class LoginSDKManager extendsSDKManager<Loginable> {

 // 单例对象

 static LoginSDKManager sInstance = new LoginSDKManager();

 private LoginSDKManager() {

  }

 // 获取单例对象

 public static LoginSDKManager getInstance() {

 return sInstance;

  }

}

在用户需要对登录系统进行管理时,通过LoginSDKManager.getInstance()就可以获取到负责管理登录系统的SDKManager,此时用户可以通过addImpl(String key, T impl)、useThis(String key)等接口对登录系统进行管理,这就可以灵活使用用户自定义的子系统。

示例

下面还是以一个示例来说明问题吧。在与用户沟通的过程中,我们发现登录模块是用户自定义概率最高的子系统。通常情况下,用户可能有自己的账户系统或者使用了第三方登录,此时用户就不需要友盟微社区SDK中附带的登录实现,完全依赖自己的账户系统或者其他第三方登录SDK来实现一个登录系统。下面我们就以实现登录系统(其他子系统的自定义原理一样)来演示自定义过程。在开始之前,我们需要对登录的抽象接口Loginable进行了解。代码如下所示:

public interface Loginable {

 public void login();

 public void logout();

 public boolean isLogined();

}

  • login():登录函数,用户需要在登录成功后将用户信息回调给友盟微社区SDK(具体过程可以参考友微社区集成文档http://dev.umeng.com/wsq/android/detail-integration#1);
  • logout():登出函数,注销用户的登录即可;
  • isLogined():用户是否登录,返回true表示已登录,否则为未登录。

微社区SDK内部通过抽象了几个简单接口来定义登录模块的功能,用户通过实现这几个函数即可定制自己的登录系统,最后将实现注入到SDK即可。例如,如果你的应用中已经有了自己的账户系统逻辑,你可以在Loginable的几个函数中通过调用你的账户系统逻辑实现这几个功能;如果你使用了友盟社会化组件那么你可以通过该社会化组件的登录、登出功能实现对应的功能,例如你可以在login()函数中调用UMSocialService对象的doOauthVerify(Context context、SHARE_MEDIA platform、UMAuthListenerlistener)接口来实现登录。

一句话概括就是:自定义一个实现了Loginable接口的类,在这个类的各个函数中调用你原有的登录、登出、判断是否已登录的函数来实现对应的功能。实现了登录类之后,通过LoginSDKManager的addImpl(String key, Loginable impl)来将该实现注入到SDK中,最后通过LoginSDKManager的useThis(String key)函数来指定要使用的登录实现,这个key就是addImpl(String key、Loginable impl)中设置的key。

自定义登录类示例代码如下:

/**

* 友盟社会化组件的登录实现,这里可以替换成自己的账户系统、第三方登录等,实现几个接口函数即可。

*/

public class SocialLoginImpl implementsLoginable {

 @Override

  public void login() {

 // 登录的具体实现,可以调用你自己的登录代码或者第三方SDK的登录函数

  }

 @Override

 public void logout() {

 // 登出的具体实现,可以调用你自己的登录代码或者第三方SDK的登录函数

  }

 @Override

 public boolean isLogined() {

 // 检测是否登录

 return true /* 代码省略 */;

  }

}

**注入登录实现 :** 

// 登录系统管理器

LoginSDKManager loginMgr =LoginSDKManager.getInstance() ;

// key

String clzKey =SocialLoginImpl.class.getName() ;

// 注入实现

loginMgr.addImpl(clzKey, newSocialLoginImpl());

// 指定使用的具体实现

loginMgr.useThis(clzKey);

为了更简单,这个过程被我们封装到一个函数中,使用的代码最后简化为 : 

// 一行代码搞定!这个函数封装了上述所有的代码。

LoginSDKManager.getInstance().addAndUse(newSocialLoginImpl()) ;

通过这几步,登录系统就被替换掉了。当微社区需要登录时,微社区SDK就会通过LoginSDKManager获取当前使用的登录实现,然后触发login()函数,此时就会执行你的登录代码了。登录成功之后,通过login()函数的回调listener(这个简单示例中没有给出该listener,具体可参考友盟微社区使用已有账户系统)将用户信息传回给友盟SDK,就完成了整个登录过程。

目前友盟微社区SDK还处在内测阶段(内测申请地址:http://wsq.umeng.com/),不过已经可以投入使用。已经有一部分集成了友盟微社区的App上线,并且运行良好。希望本文能有开发第三方Android SDK的同学一些帮助,让开发中的坑更少一些。

本文作者:何红辉,Android工程师,现任职于友盟。乐于分享,热爱开源,开源项目有AndroidEventBus、android-tech-frontier、Android源码设计模式分析。

CSDN博客:http://blog.csdn.net/bboyfeiyu,GitHub
主页:https://github.com/bboyfeiyu


新威胁:IE新漏洞允许网站跟踪鼠标 少编码多思考:代码越多 问题越多 [简讯] JDK 7u10发布 修复安全漏洞 搜狗茹立云:为何搜狗语音助手比Siri更精准? BlackBerry 10最终版SDK Gold发布 谷歌地图正式登陆App Store 为开发者推出SDK 你的云数据的三个最大威胁 公开叫板:Google不打算推出Win8版Gmail和Drive APP备案风波:开发者何去何从? 32位和64位的JVM 我该选择哪个呢? 黑莓“Got Game Port-a-Thon”活动将于12月22日在北京举行 专访Moti Joseph:浏览器安全的经验之谈 四大开源云平台的命运基因 FPS移动游戏:画质不是第一位,操控才是死穴 微软2013年的五个安全预测 应用成武器 王淮,大城小胖论辩HTML5 局部有小雨 技术人员创业后就不再适合继续编码了? Google Dremel vs Apache Hadoop 低功耗之争:英特尔 VS ARM NEIC-诺基亚体验创新中心 助力开发者创享新移动互联时代 Google地图主管Daniel Graf:新设计,新目标 浴火重生:OpenFeint创始人推开源平台OpenKit 紧随AWS数据仓库服务 Rackspace力鼎Cloudant 创业者谈:畏惧失败,但也要拥抱失败 谷歌赢得一场战斗 苹果能否赢得战争? 走进大学校园:是什么让学生成为独立开发者? 移动周报:为什么说独立开发者才是光明康途? MapFan eye:看日本地图导航应用的新玩法 数据会被清空:部分三星、魅族手机存安全漏洞 IE10简化文件访问 支持FileReader API 从MySQL迁移到MariaSQL Wikipedia力求开放 com的奇怪问题,27分 新手三层结构。问题多多。。。 jsp怎样连数据库? 高分讨教:这个vb+SQL2000的出错提示太奇怪了. 有在深圳考程序员的吗? 大家觉得电信好还是联通好啊 为什么在Win2000下我的GeForce GTS的显卡用了最新的公版驱动,在Windows优化大师中测试 一个小问题,如何在Access97数据库中创建和使用临时表??? 请问一个问题:有一个字符串,我想去掉左边固定的几个字符,剩下右边未知的几个字符!怎么做?谢谢~~ 菜鸟提问,网页上的自动变化的图片用什么作的呀? 请问哪有免费的web mail系统下载? 如何新建一个数据链接? 我想给自己的控件加一个ImageList和ImageIndex属性,选中ImageList后,在ImageIndex中显示图像列表。应如何做? 曾经的话题想改变命运的请走进来不想再说多少有自已看懂,了的曾经在这里发过言的朋友可以和我联系,QQ12545029,scaer123@163.net 如何在ASP中实现广告的按比率播放? dbedit 的问题,???????? private 里声明的函数居然调用不了? 如何得到字体的宽度和高度? ???????如果你说你对DELPHI懂,请进 SAMPLE QUESTION 在DELPHI中如何使用其他语言开发的主见? 请问LINK : warning LNK4098: defaultlib "mfcn42d.lib" conflicts with use of other libs; use /NODEFAULTLIB:library是什么含义? 请问,如何删除一个单项链表的头节点?? 怎样成为编程高手!请教高手们!! b/s程序在客户端生成EXCEL报表问题,梦天请进? 求解:如何将一幅图片或文件存入数据库??? 在用UpdateBatch方法保存纪录时VB提示:数据提供程序或其他服务返回E_FAIL状态。错误号:80004005,我死活也调不出来,还望各位高手指点一二。 菜鸟求教:要怎样去买一款满意的笔记本电脑?(29分) 我新生成一个继承自TPanel的类,但我想有其Create时,在其上放置一个TImage,请问: 急!新手请教:想查一个字符串是否存在于另一字符串中,如"asd" 不在"abca sd"中,该是哪个函数 为何网能上Ftp软件和SQL Server和Foxmail用不了? 急!!!谁有RTF文件格式中元素说明?给一份!谢先!!!!70分奉上! 请问VC中如何配置ADO(详细些)???????????????????? 关于一个DW的求和问题 问win32汇编大师(vBin等)一个非常难的问题,请看下面的源码: 请帮我看一看这个问题(关于死锁),顺便送分。 欢迎讨论jsp与ASP.NET技术 vb6+SQL2000中,在用UpdateBatch方法保存纪录时VB提示:数据提供程序或其他服务返回E_FAIL状态。错误号:80004005,我死活也调不出来,还望各位高手指点一二。 关于如何导出SQL SERVER 的数据到Excel表?? 两台PC对连问题! 一个关于ADO的连接问题,非常急!我试了好多天没进展! 在新的UNIT中我想创建一个类为什么会这样?请进吧。 恐怖!!!安装Rad Hat 7.2后,彩显报销!!!! Help Me!(简单问题) FOXpro打印与临时表的冲突? VFP高手请进。。。 继承父新生成一子类,但要屏蔽部分父类的Published或Public的Property申明属性如何做? 欢迎讨论jsp与ASP.NET技术?? 我欲展翅,我欲飞翔,我欲展翅飞翔!匆忙中,我的翅膀居然断了一个...... 怎样后台执行程序 我想工作!快想疯了 请教五城市售货员问题(即货郎担问题)分枝限界算法,机械那本书看不懂 如何去除定义为String * 256 后面的空白 全部 尖子生题库数学六年级上册总复习答案 1、已知y=-(x-2)平方+5,若-1≤x≤1,则y的最小值等于多少,y的最大值等于多少?若-1≤x≤1,则y的最小值等于多少,y的最大值等于多少? 8两题 谁有六年级上册数学复习题和答案 C语言转义字符'\ddd'代表八进制数 \后面第一个d一定要是0 才代表八进制数么 比如'\123'表示八进制数么 请将下面个数用八进制数和十六进制数表示.(1)10 (2)32 (3)75 (4)-617 (5)-111 (6)2483 (7)-28654 (8)21003 六年级上册数学课本第五单元整理和复习第2题目是什么 (4根号3分之2-10根号5分之1-根号80) 十六进制数B9A的八进制表示是? 当y=(  )时,式子7-(y+1)的平方+5有最大值,这个最大值为(   ) 计算:根号4又5分之4x根号5÷(-4分之3根号10) 求下面组合图形阴影部分的面积,答完给重赏 c语言题目:下列各无符号十进制数中,能用八进制表示的是.又有一题不解:下列各无符号十进制数中,能用八进制表示的是 A)296 B)333 C)256 D)199 求y=4的x次方+2*2的x次方的最大值 最小值 六年级数学,求解答! 求下列各阴影部份的面积六年级数学,求解答!求下列各阴影部份的面积 当x=__时,式子5-(x+3)的平方取得最大值___ 8进制转10进制小数部分怎么算八进制数3777.732转成10进制数,小数部分该怎么算? 求解答 六年级数学 阴影部分面积 在线等 式子5-|x+y|最大值为( )当取最大值时x与y关系为( ) 10的八进制是多少/ Window下创建的.txt文本文件中的数字是用2进制计数法的形式编码,还是用符号编码? 用描述法表示:8进制数 小学六年级上册语文第一单元作文 圆的面积计算公式是什么 下面的哪些答案可以用以表示八进制值8 小学六年级语文上册第一单元作文有什么可写 马上期末了,星期一就要要啊,各位英雄侠女,走个后门儿~祝愿我考个好成绩,积分多多! 人教版六年级上册数学第四单元整理与复习 若关于x的方程5x+2m=2与3x=10-2x的解相同,则m的值为? 小学六年级升学考数学试卷,高悬赏! 小学六年级上册人教版11条圆的概念 八进制的除法运算!如图,蓝线那里,2补下来怎么变成了170?为什么?结果是对的! 小学六年级升学考数学试卷,高悬赏! 答案是什么 2倍的根号3(3倍的根号75-根号2-根号27) 一道八进制运算题,求高手解答~~15×12~~注意:是八进制啊,不是十进制~~ 数列2 4 8 14 的通项公式? 式子10-(x+y)的平方;有最大值还是最小值?若有,请求最大值或最小值,此时x与y是什么关系?那么-x的平方-1呢 当25-3(a+b)的二次方有最大值时,a与b之间的关系是什么,式子的最大值是什么. 10.用八进制表示一个字节的无符号整数 ,最多需要_________A.1 位 B.2 位 C.3 位 D.4 位11.用十六进制表示一个字节的无符号整数 ,最多需要__________A.1 位 B.2 位 C.3 位 D.4 位 式子10减(x+y)的2次方,有最大值还是最小值?若有,请求出最大值或最小值,此时x与y是什么关系?现在需要 八进制码如何计算?求步聚 37.用八进制表示一个字节的无符号整数 ,最多需要__________ 苏教版小学数学六年级上册整理与复习答案 急急急急急 当a,b满足什么关系时,式子25-(a+b)的2次方有最大值,最大值是多少 4x²-7x-3-( )=2x²-3x+8括号里填什么? 将-617以八进制数表示答案是(176627)而为什么(-01151)不行呢,这两个的区别是什么? 六年级上册人教版语文第七单元作文500字 3x²-[7x-(4x-3)-2x²] 北师大六年级上册数学整理与复习一答案(包括算式)别让我说题目 人教版六年级语文上册第一单元作文第三种最好500字!写暑假生活,要用已过去的口气写,不写正在暑假的 8,10,14,16,20,22,26,28……n.用n表示第n个数,最好今晚就行```谢谢拉 越多越好如题 一个数怎样用八进制表示? 圆的面积公式怎么求?你相信吗?一个圆分成若干(偶数)等份(比如16)后,除了可以拼成近似的长方形,还可以拼成近似的平行四边形、三角形或梯形,这样拼的话同样能推导出圆的面积公式. 已知(4x²-7x-3)-A=3x²-2x+1,则A为( ).A.x²-9x+2 B.x²-9x-4C.x²-5x-2 D.x²-5x-4 (3分之1-2x)=(7分之3x+1)-3 快考了!要试卷! 六年级数学上册第三单元整理和复习2至4题的答案.化简:24:36 0.75:1 4分之3:列式要写过程:(1)张大爷养了200只鹅,鹅的只数是鸭的5分之2.养了多少只鸭?(2)张大爷养了200只鹅,鹅的只数 对于式子|a|+1,当a取何值时它有最小值?最小值是多少?对于式子2-|a -2| ,当a取何值,它有最大值?是多
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn