6.4 应用的生命周期

优质
小牛编辑
136浏览
2023-12-01

本章第一节的内容简单讲解了应用和扩展的区别,本节将为大家讲解应用和扩展的另一大区别,生命周期。

对于扩展来说,如果定义了后台脚本,同时指定persistent属性为true,那么这个扩展只要浏览器运行就会一直运行,除非用户手动去关闭它。如果声明了background权限,则这个扩展会一开机就运行,并且一直运行下去。但是对于应用来说情况会有所不同。

Chrome应用目前不允许使用永久运行的后台脚本(仅指Packaged App),无论你多么想让它一直运行下去,比如用于监听来自WebSocket的消息等,Chrome在认为应该关闭它时就会关闭它。这种做法确实有利于减少不必一直运行的应用消耗有限的内存资源,但就像上面举的例子那样,也同样会在某些方面带来局限。

既然关闭应用的行为并非开发者可以直接控制,那么我们就有必要了解应用何时开始运行,又会在何时被关闭——也就是应用的生命周期。下图给出了应用生命周期的简单图示。

enter image description here
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方法的选项对象不再支持boundsminWidthmaxWidthminHeightmaxHeight属性,请使用innerBoundsouterBounds属性代替。innerBoundsouterBounds的属性值包括widthheightlefttopminWidthmaxWidthminHeightmaxHeight

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/中应用图标的右键菜单中,选择“创建快捷方式...”),并将这个快捷方式放到系统的启动文件夹下。