本帖最后由 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: - const $ = Object.getPrototypeOf(global) || global
- import router from '@system.router'
-
- export default $.page = {
- lastPage: '',
- onShow(self) {
- if (this.lastPage === self) {
- console.log('回到前台')
- } else {
- console.log('页面显示')
- this.lastPage = self
- }
- },
- onHide(self) {
- console.log('页面隐藏')
-
- if (router.getState().name === 'System.Web') {
- this.lastPage = null
- } else {
- let t = setTimeout(() => {
- if (this.lastPage === self) {
- console.log('退到后台')
- }
-
- clearTimeout(t)
- }, 500)
- }
- }
- }
复制代码再在各个ViewModel中的onShow()和onHide()里调用: - export default {
- ...
- ...
- onShow() {
- $.page.onShow(this)
- },
- onHide() {
- $.page.onHide(this)
- },
- ...
- ...
- }
复制代码以上代码,结合前文的描述,应该一看就懂,整体代码量也不多,但实实在在解决了【退到后台】和【回到前台】的判断问题。 其中,有一段setTimeout(),大家可以自行思考下,为什么要加这段。 总之,得出此段代码的思考过程是非常有意思的,废了不少脑细胞,写出来,希望能给新手小白一些启发。
如果还有什么不明白的地方,欢迎随时来咨询,个人微信:parith。
|