请选择 进入手机版 | 继续访问电脑版
 找回密码
 立即注册
搜索

技术分享 快应用开发技巧之判断退到后台篇

1
回复
2157
查看
[复制链接]

5

主题

5

帖子

50

积分

 楼主| 2019-10-28 12:15:46 显示全部楼层 |阅读模式
本帖最后由 zephyrtune 于 2019-10-28 12:15 编辑
最近碰到一些开发者在咨询:快应用“如何判断退到后台”的问题。 正好之前在写功能的时候,也遇到过这个问题,我觉得可以和大家分享下我的经验。
解决这个问题的时候,确实费了我不少脑细胞。 作为一个已入坑的老人,想对新入坑的开发者说一句:不入不知坑深,一入一坑到底!
玩笑归玩笑,问题归问题,需求还是要解决的。
目录:

  • 【生命周期】探索
  • 【退到后台】实现原理
  • 【回到前台】及【特殊场景】处理
  • 【代码实现】

【生命周期】探索
快应用的生命周期,我就不再赘述了,大家可以参考官方文档:https://doc.quickapp.cn/tutorial/framework/lifecycle.html
可以看到快应用提供了2个APP级别的事件,7个页面级别的事件、2个页面状态变量。
在这所有的事件和变量里面,没有为【退到后台】和【回到前台】提供单独的回调事件。 所以解决这个问题,变得有些棘手,尤其当时还是新手的我,略懵!
但需求还是要做,不过需求延期了。(这里要感谢下领导,还是比较宽容的!)
期间我把所有的事件回调都调试了一遍,依然没什么收获。一番折腾以后,我决定还是把所有的目光都聚焦到onHide()和onShow()这两个事件上。
单独看onHide()这个事件,它在页面被切换隐藏时调用,不管页面是【跳转】还是【退到后台】,都会触发这个事件。 所以只要能把【跳转】和【退到后台】区分出来,问题就引刃而解了。
想到这一点的我,感觉眼前一切光明!但具体如何区分呢?瞬间又让我陷入了深深的沉思之中。
抬头望天,天花板让我别看,它就是天。再看看周围的小伙伴,他们的眼神中似乎散发出一种诡异的光芒,仿佛在提醒我一个事实:你是我这辈子见过的最销魂的懵逼!
但四分之一炷香之后,我会让他们知道,我解决了这个问题。虽然本人生平解决过无数问题,但是这一次,我认为是最开心的。 做开发,写代码呢,最重要的就是开心……
【退到后台】实现原理
在翻了【TVB经典台词100句】和【快应用开发文档】之后,我收到线报,说:router.getState().name,可以拿到当前页面的名称。 意思是说通过页面名称来判断【页面跳转】和【退到后台】。
我问线人:你是不是想说,【页面跳转】的名称不一样,而【退到后台】的页面名称是一样的?。
线人斩钉截铁地说:是!
(我若有所思,这样判断真的可行么?有没有内鬼?会不会出意外?)
突然,我厉声喝道:臭小子,你耍我么?
线人一惊:阿Sir,相信我,这是刚刚得到的最新消息……
我:如果对方同名同姓怎么办?就比如一个商品页跳另一个商品页,他们都一个名字,只是id参数不同而已。你说这是跳转?还是退到后台?
线人:……
(通过页面名称判断的方式应该是不可行了,但我灵机一动,久违的笑容不禁出现在脸上)
我:你这消息虽不准确,但也有一定价值,我们可以把判断方式改一改,改成比较页面对象,这样就行了!
线人:阿Sir,好厉害!阿Sir,好威武!
我:嘿嘿嘿!
就这样,我写了【退到后台】的第一个版本,但后来发生的一件事情,让我觉得这个版本还是有些不足之处……
【回到前台】及【特殊场景】处理
正当我根据【退到后台】的经验,写【回到前台】的逻辑时,正当我以为无往不利,大功即将告成之时,突然手机响起:有内鬼终止交易!
我:……
(此时的我,心里的崩溃和绝望,如同瞬间跌落谷底,我想去天台透透风!)
(站在天台屋顶边,世界变得如此的渺小,以往我也无数次站在这个位置,以同样的角度看着所有的一切。 但这一次我看不清楚!一切都变得那么暗淡朦胧!)
(兜里的iPhone突然振了一下。我摸出手机,定睛一看!我擦!原来现在是凌晨4点…………………………)
(手机上的内容写的是:你不是开发快应用的吗?为什么用iPhone?!)
我:……
(就在此时,背后突然有人大喊:别跳楼,这个月的指标用完了,不准跳!)
我:……
(我回头看了一眼,原来是他!)
我:保安做的还习惯吧?
他:习惯!到哪不是为人民(币)服务?!
我:上个月往你二姑家表弟帐上打得钱收到了吧?
他:收到了。就是税扣得有点多,肉疼!
我:你那身懒肉,是该减减肥了!好好干吧,总有一天你会搬进汤臣一品的!因为马云说,未来的房子会变成白菜价的!
他:……
我:刚刚的短信是怎么回事?
他:你说内鬼那事?
我:嗯!
他:我打听到,快应用router接口是可以直接跳网页的,可能会影响上面的逻辑判断。
我:router.push()和router.replace()?
他:是的,就是这两个内鬼。
我:嗯,如果是网页地址的话,他们会调用System.Web打开网页,虽然页面被切走了,但新页面中,并没有触发我们自定义的onShow()和onHide()事件, 所以会导致上面的判断逻辑失效。
他:对!
我:咱们可以单独写个ViewModel来承接所有的WebView页面,你说问题是不是就解决了?
他:好主意!这么好的主意,咱要不要先拆包辣条庆祝一下?
(我投过去鄙夷的眼神,一包哪够分?还不够你个胖子塞牙缝的!)
我:辣条还是你吃吧!我觉得还有一种思路,也可以解决这个问题。
他:还有一种?
我:嗯!只要对System.Web做一个特殊判断就可以了!
他:咋弄?
我:看代码吧!talk is cheap, show you my code.
【代码实现】
先定义一个公共lib,page.js:
  1. const $ = Object.getPrototypeOf(global) || global
  2. import router from '@system.router'
  3. export default $.page = {
  4. lastPage: '',
  5. onShow(self) {
  6. if (this.lastPage === self) {
  7. console.log('回到前台')
  8. } else {
  9. console.log('页面显示')
  10. this.lastPage = self
  11. }
  12. },
  13. onHide(self) {
  14. console.log('页面隐藏')
  15. if (router.getState().name === 'System.Web') {
  16. this.lastPage = null
  17. } else {
  18. let t = setTimeout(() => {
  19. if (this.lastPage === self) {
  20. console.log('退到后台')
  21. }
  22. clearTimeout(t)
  23. }, 500)
  24. }
  25. }
  26. }
复制代码
再在各个ViewModel中的onShow()和onHide()里调用:
  1. export default {
  2. ...
  3. ...
  4. onShow() {
  5. $.page.onShow(this)
  6. },
  7. onHide() {
  8. $.page.onHide(this)
  9. },
  10. ...
  11. ...
  12. }
复制代码
以上代码,结合前文的描述,应该一看就懂,整体代码量也不多,但实实在在解决了【退到后台】和【回到前台】的判断问题。 其中,有一段setTimeout(),大家可以自行思考下,为什么要加这段。 总之,得出此段代码的思考过程是非常有意思的,废了不少脑细胞,写出来,希望能给新手小白一些启发。
如果还有什么不明白的地方,欢迎随时来咨询,个人微信:parith。
回复

使用道具 举报

3

主题

25

帖子

140

积分

2019-11-4 17:53:32 显示全部楼层
你这货终于更新啦
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册