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

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

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

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 显示全部楼层
你这货终于更新啦
回复

使用道具 举报

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