概述
下面我们来分析一下erget中的生命周期。
src/egret/player/SystemTicker.ts:
export namespace lifecycle {
export type LifecyclePlugin = (context: LifecycleContext) => void;
/**
* @private
*/
export let stage: egret.Stage;
/**
* @private
*/
export let contexts: LifecycleContext[] = [];
let isActivate = true;
export class LifecycleContext {
pause() {
if (isActivate) {
isActivate = false;
stage.dispatchEvent(new Event(Event.DEACTIVATE));
if (onPause) {
onPause();
}
}
}
resume() {
if (!isActivate) {
isActivate = true;
stage.dispatchEvent(new Event(Event.ACTIVATE));
if (onResume) {
onResume();
}
}
}
onUpdate?: () => void;
}
export let onResume: () => void;
export let onPause: () => void;
export function addLifecycleListener(plugin: LifecyclePlugin) {
let context = new LifecycleContext();
contexts.push(context);
plugin(context);
}
}
LifecycleContext定义了监听生命周期的类,pause(),resume(),update()这个三个成员方法分别执行暂停、继续和刷新。LifecyclePlugin定义了一个监听应用程序状态变化的函数类型,它有一个类型为LifecycleContext的context参数。addLifecycleListener()方法创建了LifecycleContext的一个实例,把这个实例作为参数调用了传入的plugin()方法。
这样看好像有点乱,我们梳理一下。
分析
type LifecyclePlugin
export type LifecyclePlugin = (context: LifecycleContext) => void;
因为不同平台监听应用程序状态变化的实现不同(Native平台要应用到原生接口,Web使用一些Javascript的API),它们的共同点是要用到LifecycleContext的一个实例,在对应的监听实现代码里去调动这个实例的pause(),resume(),update()这三个方法去暂停、继续和刷新应用程序,所以定义了LifecyclePlugin这个函数类型。
function addLifecycleListener
export function addLifecycleListener(plugin: LifecyclePlugin) {
let context = new LifecycleContext();
contexts.push(context);
plugin(context);
}
addLifecycleListener()方法作为桥梁,接收到具体的LifecyclePlugin类型的函数,创建LifecycleContext的一个实例作为参数调用它。
class LifecycleContext
let isActivate = true;
export class LifecycleContext {
pause() {
if (isActivate) {
isActivate = false;
stage.dispatchEvent(new Event(Event.DEACTIVATE));
if (onPause) {
onPause();
}
}
}
resume() {
if (!isActivate) {
isActivate = true;
stage.dispatchEvent(new Event(Event.ACTIVATE));
if (onResume) {
onResume();
}
}
}
onUpdate?: () => void;
}
export let onResume: () => void;
export let onPause: () => void;
isActivate作为一个布尔值类型的成员属性用来标记当前是否暂停,这个if语言的作用是防止重复触发暂停事件,如果触发,主要做了两件事情,一个是向全局事件系统触发了一个Event.DEACTIVATE类型的事件(关于全局事件系统在后面的章节中具体分析)。一个是调用了onPause()方法。我们在egret-core/tools/templates/game/src/Main.ts中找到这几行
private onAddToStage(event: egret.Event) {
egret.lifecycle.addLifecycleListener((context) => {
// custom lifecycle plugin
context.onUpdate = () => {
console.log('hello,world')
}
})
egret.lifecycle.onPause = () => {
egret.ticker.pause();
}
egret.lifecycle.onResume = () => {
egret.ticker.resume();
}
//设置加载进度界面
//......
//初始化Resource资源加载库
//......
}
/**
* 心跳计时器单例
*/
export let ticker: sys.SystemTicker = new sys.SystemTicker();
这里延迟定义了onPause()方法,这个方法只有一行,执行了egret.ticker.pause()方法。resume()方法类似pause()方法。
使用例子
Web平台
Native平台
egret-core/src/egret/native/NativeHideHandler.ts:
namespace egret.native {
/**
* @private
*/
export let NativeLifeCycleHandler: egret.lifecycle.LifecyclePlugin = (context) => {
egret_native.pauseApp = () => {
context.pause();
egret_native.Audio.pauseBackgroundMusic();
egret_native.Audio.pauseAllEffects();
};
egret_native.resumeApp = () => {
context.resume();
egret_native.Audio.resumeBackgroundMusic();
egret_native.Audio.resumeAllEffects();
};
}
}
这个Native平台监听函数定义了原生平台的两个方法egret_native.pauseApp()和egret_native.resumeApp()。pauseApp()函数做了两件事情:暂停应用程序,暂停背景音乐和音效的播放。resumeApp()类似。
egret-core/src/egret/native/NativePlayer.ts:
namespace egret.native {
/**
* @private
*/
export class NativePlayer extends egret.HashObject implements egret.sys.Screen {
//...
private init(option: PlayerOption): void {
//...
lifecycle.addLifecycleListener(NativeLifeCycleHandler);
//...
}
//...
}
}
这里利用addLifecycleListener()方法绑定了NativeLifeCycleHandler()这个函数。