6.4 应用的生命周期
本章第一节的内容简单讲解了应用和扩展的区别,本节将为大家讲解应用和扩展的另一大区别,生命周期。
对于扩展来说,如果定义了后台脚本,同时指定persistent
属性为true
,那么这个扩展只要浏览器运行就会一直运行,除非用户手动去关闭它。如果声明了background
权限,则这个扩展会一开机就运行,并且一直运行下去。但是对于应用来说情况会有所不同。
Chrome应用目前不允许使用永久运行的后台脚本(仅指Packaged App),无论你多么想让它一直运行下去,比如用于监听来自WebSocket的消息等,Chrome在认为应该关闭它时就会关闭它。这种做法确实有利于减少不必一直运行的应用消耗有限的内存资源,但就像上面举的例子那样,也同样会在某些方面带来局限。
既然关闭应用的行为并非开发者可以直接控制,那么我们就有必要了解应用何时开始运行,又会在何时被关闭——也就是应用的生命周期。下图给出了应用生命周期的简单图示。
Chrome应用的生命周期,图片来自developer.chrome.com
Event Page就是Chrome应用的后台脚本,它用于监听各种事件。当用户运行应用,Event Page加载完成后,onLaunched
事件就会被触发。如果这个应用运行后要向用户提供一个窗口,就是在onLaunched
事件触发后后台脚本创建的。当这个窗口被关闭后,并且Event Page也没有需要处理的任务,Chrome就会彻底关闭这个应用——连同Event Page一起关闭。在关闭应用前会触发onSuspend
事件,这个事件可以提醒应用的后台脚本应用即将被关闭,以给应用一个准备退出的机会。
每一个应用都会有一个Event Page,可以通过Event Page监听onLaunched
事件,然后创建一个窗口。在Manifest的app
属性中,通过background
域定义Event Page。
"app": {
"background": {
"scripts": ["background.js"]
}
}
然后在background.js中指定应用启动时创建窗口1。
1 从Chrome 36开始,create
方法的选项对象不再支持bounds
、minWidth
、maxWidth
、minHeight
和maxHeight
属性,请使用innerBounds
和outerBounds
属性代替。innerBounds
和outerBounds
的属性值包括width
、height
、left
、top
、minWidth
、maxWidth
、minHeight
和maxHeight
。
chrome.app.runtime.onLaunched.addListener(function() {
chrome.app.window.create('main.html', {
id: 'MyWindowID',
bounds: {
width: 800,
height: 600,
left: 100,
top: 100
},
minWidth: 800,
minHeight: 600
});
});
有关在应用中创建窗口的具体内容将在下一节给出。
在应用首次被安装或者更新到新版本时,会触发onInstalled
事件,Event Page可以在此事件触发时做一些初始化任务,如向本地写入默认设置、向用户展示欢迎窗口等等。
Chrome应用可以使用chrome.storage
存储数据,如:
chrome.runtime.onInstalled.addListener(function() {
chrome.storage.local.set(object items, function callback);
});
数据保存在用户本地时,可能会面临数据永远丢失的风险——当用户卸载应用或者重新安装操作系统后,应用保存在本地的数据都会永久丢失。为防止这种风险,可以选择使用一种在线的存储方式,最简单的方法就是使用Chrome storage API中的sync
域储存数据:
chrome.runtime.onInstalled.addListener(function() {
chrome.storage.sync.set(items, function(){...});
});
这样这些数据会随Chrome在线同步保存在Google的服务器中。这对诸如应用设置等数据非常重要,因为用户也许会有一天重新安装卸载掉的应用。
最后当Chrome认为一个应用处于空闲状态时就会清理掉这个应用的进程,在清理之前会触发onSuspend
事件,以让Event Page在退出前有机会做一些清理工作,从而不会导致意外退出。
有一种办法可以让应用一直保持运行,就是永远都不关闭前端窗口——当用户关闭窗口时隐藏它而不是真的关闭,或者让后台直接创建一个隐藏的窗口,这样前端窗口就可以一直运行且不显示出来。当用户再次启动应用时,再显示出来就可以了。
虽然也可以使用setInterval
定期做一些简单的任务,如每10秒就让Event Page做点什么,但是Chrome清理应用进程的时间间隔是可以通过指定参数更改的,并且将来很有可能会发生变化,所以这种方法并不值得推荐。
对于个别应用确实需要长时间在后台运行,Google也清楚这一点,但是为什么Chrome应用却不提供background
权限呢?按照Chromium开发者的说法,由于要专门为应用提供system tray特性,应用可以通过这一特性常驻后台,在没有提供这一特性前,为了防止应用开发者依赖background
权限,所以禁用了它。
那么现在的情况就比较尴尬了,system tray尚未实现,background
权限又已被禁用,所以如果想让应用随系统启动并常驻后台,目前一种可行的方法——虽然笨拙但却有效,安装一个拥有background
权限的扩展,这样可以让Chrome一直运行;在Event Page中添加一个setInterval
任务以防止被Chrome认为应用处于空闲状态;创建一个Chrome应用的快捷方式(在chrome://apps/中应用图标的右键菜单中,选择“创建快捷方式...”),并将这个快捷方式放到系统的启动文件夹下。