关于移动平台工程的一些心得

        做Android也有一年多了,因为在小公司么,项目经历了无数,精品确实是不太多...不过好歹是自已做过了一些东西,而且最近的IM项目,让我去搭架构了,目前看来稳定性有一些欠佳,但是至少我是没有太失望的,我觉得这个时间,这个进度也还行了,即使这是个外包项目,我拒绝为了做得特别快而极混而不想,再说,不想不去一直修改重构的话,怎么可能稳定呢?  
       但是也是有一些东西值得思考的,已经做了很多项目了,应该有一些显示的经验或教训了,应该不至于像以前一样拿起来后,也没有太多的顾忌,直接就想架构后就直接开写了,今天下午在一次次RemoteService ANR 的苦闷中,我萌生了写这篇博客的念头。
       还是先从今天引起反思的起因事件写吧,起因是为啥呢?RemoteService ANR了,那ANR是为什么呢? 很简单XMPP的网络请求数据,数据的写入数据库我都没有放入线程中写。那为什么我当年在构造这些函数时没有用线程+异步,也一年经验了怎么会犯这错误呢? 那回忆一下吧,其实在开始构造Remote Service时,我确实是想到了异步,但是当时并没有用,一是因为觉得可能没有这么严重吧(那时离作××APP的帐户系统时已经有些久远了,已经忘记了当时异步的极端重要性),二是对Remote Service的秉性不太熟悉,觉得一个后台进程,不开线程自已也是一个线程啊,相对我Activtiy完全是异步么..,当然现在明白这是完全完全错误的想法..Remote Service 是Service 是组件,而不是线程,必然不是想像中那样用的。


---------


      那于是今天先反思一下××APP帐户系统当时的架构,当时是单例的AccountSys作为了中枢系统,UI这端比如是一个Activity注册了AccountSys的回调接口之后,直接调用AccountSys的函数,而这个函数在另一个线程中从网络下载完后,就会处理存储更改数据库这类事情,处理数据库的类叫DBHelper,AccountSys也注册了DBHelper的一个回调接口,在线程中作完网络下载之后,其会调用DBHelper的函数进行数据库操作,但是这个操作也是异步的,操作后AccountSys会响应了DBHelper的回调接口。(这时说明DBHelper的数据库操作已经做完了,并告知了AccountSys了),这时AccountSys再执行其相对于Activity(即UI)的回调函数,这样UI便得到了最终网络和数据库操作完成了结果。
       大体还记得那时出现了一些什么样的Bug,首先,因为AccountSys是单例的,同时只能一个AccountSys作为其回调对象,怕时有几个功能几乎很近发生时,会有回调被挤掉而不能完成。这种可能性理论上绝对是存在的,就算是一个Activity有不同的操作很近发生,AccountSys的回调都有可能响应不过来。我一度想作一对多的观察者模式,因为可以同时响应多个。不过后来做完后,虽然我没改这个架构,但却从来没发生过问题,个人很庆幸,算完工了。 而AccountSys与DBHelper的调用与回调就没出现问题,因为Application只有一个AccountSys实例,而AccountSys又只有一个DBHelper实例..
      第二个后来比较难处理的事情,是后来操作太多了,我只得给这些操作,无论是AccountSys面向UI的操作,还是DBHelper面向AccountSys的操作,都有好多了,而不同的调用面向不同的回调方法,这个真是蛮费事的啊。后来就是在回调接口switch case 完成的..例了十来个功能,后来也没有再重构了。
     话说回调,当时发生了跨线程的回调了的问题,回调接口里边的函数是发生回调的代码那里执行的,如果发生回调的地方是别一个线程中,那回调的实现函数很可能和这个函数所在类不是一 个线程中。


----------
      话说现在的IM项目,其实也是一样的,而且还多了更大范围的调用与回调,即跨进程的调用和回调。当然这个架构基本还是正确的,用messager的方法,大体也够用,也有一些问题。下边总结下下吧:
      说到调用与回调,消息机制肯定撤不开了,在我这里的消息指的是什么呢?指的是调用时发过去的 信息 与回调时返回来的 信息,因为不同的调用方法与回调返回的信息是不同类型的,所以把这个地方统一好,还是非常重要的。比如这次的跨进程传送,我用的是ServiceCmd 进行传送,因为中途是要跨进程携带消息的,只能用Bundle,那我每个ServiceCmd都有用Bundle的初始化函数,这样我有数据的变动封装到了 那些Cmd中,无论是 客户端(对我来说是用BgService的Activity)还是服务端(就是Service),都没有显示出Cmd内部包装的变动。应该说,这个包装应该不是很完全,而且必然有很多改进甚至很大改进,但是我的想法初步落实了,而且我比较用心想了,我是蛮开心的。


      还有上次那种可能取代的回调,被我用addListener与hashcode的方法化解了,我是认真构思、实现而且效果不错的,我非常开心,从此那个回调可能出问题的事就这样解决了。

      ......

      要说上一部分的实现哪里需要改进,我个人认为Proxy与Service的switch,都把CMD给解了一下才去找功能,有没更好的,把传输给封装起来,调用和真正功能的封装在一起的可能?

      还有比如Login那里,点多次重复发消息可能挂掉的问题,怎么样杜绝一下好。其实说到这里,我也有那觉得有必要作消息撤消(即发过去的东西不返回结果就可以了..)机制,还有多长时间不可以发重复功能的消息的机制。或者同样的消息,上一个没返回,下一个不能发出去的机制, 这几个作为比较操作逻辑完善的消息机制来说,非常重要。对于我现在这个Login的问题,很可能用第三个或第一个机制可以解决的。


      第二就是BgService中的网络与数据库,大量的没开线程,这个显然不对了,我都忘了当年××APP的帐户系统时,我是怎么样所有网请和数据库都作线程的了,这里的话,concurrent包也线程池有必要用得更熟练一些。
      
-----------

      说完消息机制后,也说说异步与UI的矛盾处理方法,其实也是因为今天的现象引起的。在开程序后我点登陆后,竟然有一二秒钟Dialog没有出来,我迫不急待其出来,于是又点了一下,于是挂了..,且不说挂的原因,我觉得UI反应灵敏太重要了,其实比如消息发送后等待回调的缓冲的地方你说多少100毫秒不是很重要的,对用户体验没太大影响的,相反前者影响很大。所以以后要坚决把UI响应及时响应出来,有可能卡的功能在其后哪怕立刻做也没问题,想想UC的UI,就是比360浏览器等的UI流畅一些,就好用很多的样子,以后我也要做UI的,这个经验太重要了。
      
      此外,本次数据库的同步关键字和开闭问题也需要继续琢磨,我的模式还不清晰,还没想到非常好的办法,但要在这里记一下。


-----------
      心血来潮,最近关于产品与技术的心得就先写这么一篇文章吧,异步处理系架构大局,系面向对象的典型运用,系MVC之明朗程度,我还要继续构思、实验、重构、学习。以后这种架构使用,我相信我会用得非常好的。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值