您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
   
 
 
     
   
 订阅
  捐助
Android UI:机智的远程动态更新策略
 
作者:王金波 来源:腾讯Bugly 发布于: 2015-10-23
  1807  次浏览      30
 

摘要:做过Android开发的人都遇到过这样的问题:随着需求的变化,某些入口界面会出现UI的增减、内容变化和跳转界面变化等问题。本文作者给出了一套方案来解决动态更新UI的问题以及更好地解决未读提醒的逻辑。

本文作者为腾讯Bugly特约撰稿人:腾讯自选股客户端工程师 王金波

问题描述

做过Android开发的人都遇到过这样的问题:随着需求的变化,某些入口界面通常会出现UI的增加、减少、内容变化以及跳转界面变化等问题。每次发生变化都要手动修改代码,而入口界面通常具有未读信息提醒这样的“小红点”逻辑;一旦UI变化,“小红点”逻辑也要重新计算。如果不同的RD来维护这些代码,耦合性非常高,出错概率也很大。本文以自选股的个人页卡为例(界面如下图所示),给出了一套方案来解决动态更新UI的问题以及更好的解决未读提醒的逻辑。

旧的方案(Phase out)

  • 对于UI动态变化的问题,通常结合远程控制来解决。
  • 以上图的“资产管理”为例,旧的解决方案会在XML写死全部的item,如:“港股交易”、“基金交易”和“精品理财”这三个item。然后根据后台传递过来的JSON解析出需要隐藏哪些item。点击不同的item会跳转到不同的activity(如下图所示),这部分跳转操作也是写死在代码中的。

    这解决了一部分问题,但是如果需求新增了item,比如新增了“沪深交易”、“美股交易”,那就需要改动现有代码了。

  • 对于未读指示(小红点)功能,它的作用是,有未读信息来了,需要在UI上面显示一个小红点提醒用户。比如下图的股友动态的头像提醒,资产管理的“NEW”提醒,系统设置的新版本提醒等。
  • 旧的方案是定义了一个int型(32位),用它的每一位代表一个UI上的item。比如好友动态是第1位,未读提醒是第2位... “小红点”思想是哪个item有未读信息,则该int型对应的那一位就置1,否则为0。一旦某个item有未读提醒的改变,则将这个int型对应的位改变,异步写入SharedPreference中,同时利用观察者模式通知UI做更新,如下图所示:

    上述做法总体来说最大的缺陷就是没有做到“开放-封闭”原则。面对扩展的时候,即添加一个item则不得不修改现有代码,需要在该int型中添加一位标志位,观察者模式也要注册新item。所以下面我会介绍另一种方案可以更好的解决该问题。

    新的解决方法

    数据抽象

    首先进行数据的抽象,并将UI进行分组,如下图所示:

    按照组合模式,将数据以树形结构组织起来,表现“整体/部分”层次结构,如下图所示。这样做的好处是,可以以一致的方式来处理个别对象以及对象组合。蓝色的表示节点,而绿色的表示叶节点。

    组合模式的类图,如下所示:

    对UI进行的数据抽象。无论是ListItem列表项,还是GridView Item的项,都采用了PersonalItem对象来表示,如下所示:

    对于PersonalItem来说,有些没有意义的方法就不实现,如add()、remove()、getChild()等,调用它们会抛出UnsupportedOperationException()异常。

    完美解决未读提醒(小红点)的问题

    关于计算小红点,PersonalGroup类利用组合+迭代器的模式,代码如下:

    这里使用了迭代器,用它遍历所有PersonalComponent组件。遍历过程中可能遇到PersonalItem也可能遇到PersonalGroup。由于它们都是PersonalComponent,且实现了getUnreadIndicator()方法,那我们只需调用getUnreadIndicator()即可。

    如上图所示,PersonalGroup中加载的是PersonalComponent,可能是PersonalItem也可能是PersonalGroup。组合模式的优点就是无视具体类型 -- 获取出来的都是PersonalComponent,然后利用多态,调用具体类的getUnredIndicatorCount()方法。如果是PersonalGroup,则继续调用它的这个方法(与此方法一样,会开始另一个遍历);如果为PersonalItem,则说明遍历到了树形结构的末端(即叶节点),则进行如下处理:

    如果getUnreadIndicator为true,则表示该PersonalComponent需要显示小红点。因此,利用上述组合+迭代方式,运用递归在根节点处进行一次调用即可。如下图所示,当计算出叶节点“A股大赛”有未读提醒,则它上级的groups也有未读提醒,一直统计到根节点。

    getUnredIndicatorCount()是每一个item自己来决定自己是否需要展示小红点的方法。这就是将局部与整体解耦了。整体上面,需要计算小红点,至于如何计算则委托给具体类来实现。即面向对象中的将 "做什么" 与 "怎么做"分开。RD可以从中解放出来,不必关注整体实现,只需关注自己的实现即可。比如,需要在“资产管理”中添加“美股交易”,RD只需添加“美股交易”的内容即可。下一节会说明,这部分内容也由远程控制来代劳了,远程控制传递过来的Date与本地存储的Date比较,如果是新的Date值,则证明这个item为“NEW”,则对应的小红点需要显示。

    远程控制动态更新UI

    当远程控制发生变化时(5分钟主动发一次请求),通过解析远程控制接口返回的JSON串,生成PersonalItem对象的列表。其中每一项对应UI上面的一个item。需要注意的是,这里还包含了一个URL,它是点击UI控件跳转的URL。以“资产管理”为例,它包含“沪深交易”、“基金交易”等子项。当点击任意一个子项的时候启动的是同一个Activity - WebviewActivity,它包含一个WebView控件。因为每个子项的跳转URL不一样,所以这个WebView load了不同的URL,即完成了跳转不同界面的问题。 然后按照上面描述的树形结构,把PersonalItem放到Groups中。如下图所示:

    Model存储了待显示的数据结构。这份数据通过Parser的解析生成UI的内容。过程如下图所示:

    Parser模块是一个递归函数,递归的对Model进行解析。并将解析出来的List Item、Grid Group、GridView Item加载各自的XML文件,在程序中动态的添加UI组件。其中onClick事件是在定义PersonalItem的时候已经写好了回调。例如,“资产管理”属于Grid Group,其子项“沪深交易”、“基金交易”等属于GridView Item。在上述“Build PersonalItem Objects”步骤中,已经定义了onClick方法,调用onClick方法跳转至WebViewActivity,这个Activity会加载不同GridView Item的URL,从而实现点击不同item跳转不同页面的目的。

    Note:

    对于ListItem元素,即上图的列表项(不是GridView元素),并没有实现远程更新的策略。因为它们跳转的逻辑是跳转到各自的Activity,是固定不变的;并且它们的文字描述、图标、是否隐藏均不需要后台来控制更新。故实际项目中,只对GridView内容作了远程控制动态更新UI机制的处理。

    另外,在通过远程控制动态更新UI的过程中也遇到了一些坑,比如远程控制更新的时刻,恰好用户退出App,此时系统刚好销毁Activity。那么在执行到上述Parser模块的inflateUI的时候就需要判断当前上下文是否为空,如果为空则直接退出。

    结论与数据

    本文通过将UI数据进行抽象,利用组合模式进行数据的构建,利用递归的方式将数据映射为UI,同时处理了点击事件。数据源则可以通过远程控制动态的更新,RD从中解放。另外,组合+迭代器的方式完美的解决了小红点的问题,遵循了“开放-封闭”原则,将“做什么”与“怎么做”分开。下图从数据的角度描述了改版前后代码量、Bug量以及RD工作量的差异。

       
    1807 次浏览       30
     
    相关文章

    手机软件测试用例设计实践
    手机客户端UI测试分析
    iPhone消息推送机制实现与探讨
    Android手机开发(一)
     
    相关文档

    Android_UI官方设计教程
    手机开发平台介绍
    android拍照及上传功能
    Android讲义智能手机开发
    相关课程

    Android高级移动应用程序
    Android系统开发
    Android应用开发
    手机软件测试
    最新活动计划
    嵌入式软件架构设计 12-11[北京]
    LLM大模型与智能体开发实战 12-18[北京]
    嵌入式软件测试 12-25[北京]
    AI原生应用的微服务架构 1-9[北京]
    AI大模型编写高质量代码 1-14[北京]
    需求分析与管理 1-22[北京]

    android人机界面指南
    Android手机开发(一)
    Android手机开发(二)
    Android手机开发(三)
    Android手机开发(四)
    iPhone消息推送机制实现探讨
    手机软件测试用例设计实践
    手机客户端UI测试分析
    手机软件自动化测试研究报告
    更多...   


    Android高级移动应用程序
    Android应用开发
    Android系统开发
    手机软件测试
    嵌入式软件测试
    Android软、硬、云整合


    领先IT公司 android开发平台最佳实践
    北京 Android开发技术进阶
    某新能源领域企业 Android开发技术
    某航天公司 Android、IOS应用软件开发
    阿尔卡特 Linux内核驱动
    艾默生 嵌入式软件架构设计
    西门子 嵌入式架构设计
    更多...