管理应用的生命周期

与世界上的所有事物一样,应用也有生命周期。它们会安装、运行、重新启动,在系统需要释放资源时会暂停,还会被卸载。该实验将向您展示 Chrome 应用生命周期的基础知识,以及它的核心——事件页面(即后台脚本)是如何使用的。

事件页面

事件页面是 Chrome 应用最重要的部分之一,它负责确定运行的内容、时间与方式。例如,如果您的应用是一个即时通信工具,您可能希望您的事件页面在有新消息时才显示用户界面。

对于较小的应用,事件页面监听应用生命周期事件,并作出合理的反应。有两个重要的生命周期事件,包括 app.runtime.onLaunchedapp.runtime.onRestarted

onLaunched 事件

app.runtime.onLaunched 事件是最重要的事件,当用户为了执行而单击您的应用图标时产生。对于大多数较简单的应用来说,事件页面应该监听该事件并在它产生时打开一个窗口。有关这一常见用法,请参见我们的 AngularJS main.js JavaScript main.js

指定了标识符的窗口

app.window.create 方法可以将标识符和打开的窗口关联。目前,最有意思的用途是在应用执行时恢复窗口的宽度、高度和位置,以及与之关联的开发者工具窗口(如果打开的话)。

执行您现在的应用,移动并调整窗口的大小,关闭后在重新启动,应用还是会在原来的位置重新打开,是吗?现在在 AngularJS main.jsJavaScript main.js 中添加一个 id 属性,重新加载应用并再次测试:

chrome.app.runtime.onLaunched.addListener(function() {
    chrome.app.window.create('index.html',
      {id: 'mainwindow', bounds: {width: 500, height: 309} });
  });

如果您的应用程序需要的话,您可以打开一个以上的窗口。

onRestarted 事件

app.runtime.onRestarted 事件不像 onLaunched 那样重要,但是它可能和某些类型的应用相关。当应用重新启动时,例如当 Chrome 浏览器退出、重新启动,再次运行应用时,将会执行该事件。您可以利用该事件恢复临时的状态。

例如,如果您的应用有一个表单,包含多个字段,您不会在用户输入时就保存部分的表单。如果用户特意退出您的应用,他们不一定希望保留这部分数据。如果 Chrome 运行时环境由于用户意图以外的原因重新启动,在应用重新启动时用户可能还需要这些数据。

让我们更改我们的代码,将待办事项输入字段保存在 storage 中,只有在 onRestarted 事件触发时才恢复它。

注意:我们之前学习了 chrome.storage.sync,但是直到现在才提到了 chrome.storage.local。它们有完全相同的语法,但是正如它的名称所述,chrome.storage.local 的含义完全是本地的,而不会尝试同步或者将数据保存到云端。

更新事件页面

更新事件页面,包含 onLaunched onRestarted 事件。在 AngularJS main.js JavaScript main.js 处理事件的方式相同:

chrome.app.runtime.onLaunched.addListener(function() {
  // normal launch initiated by the user, let's start clean.
  // note that this is not related to the persistent state, which is
  // appropriately handled in the window code.
  runApp(false);
});

chrome.app.runtime.onRestarted.addListener(function() {
  // if restarted, try to get the transient saved state
  runApp(true);
});

function runApp(readInitialState) {
  chrome.app.window.create('index.html',
    {id: 'mainwindow', bounds: {width: 500, height: 309} },
    // the create callback gets a reference to the AppWindow obj
    function(win) {
      // when the callback is executed, the DOM is loaded but no script was
      // loaded yet. So, let's attach to the load event.
      win.contentWindow.addEventListener('load', function() {
        if (readInitialState) {
          win.contentWindow.setInitialState();
        } else {
          win.contentWindow.clearInitialState();
        }
      });
    });
}

更新控制器

添加到现有的 AngularJS controller.js JavaScript controller.js

Angular
JavaScript
var newTodoInput = null;

var clearInitialState = function() {
  chrome.storage.local.set({'newtodo': null});
}

var setInitialState = function() {
  chrome.storage.local.get('newtodo', function(data) {
    if (newTodoInput && data && data.newtodo) {
      newTodoInput.value = data.newtodo;
      newTodoInput.focus();
    }
  });
}

window.addEventListener('load', function() {
  var saveTransientState = function() {
    chrome.storage.local.set({'newtodo': newTodoInput.value});
  };
  newTodoInput = document.querySelector('input[type="text"]');
  newTodoInput.addEventListener('keypress' , function() {
    saveTransientState();
}) })
  var newTodoInput = document.querySelector('input[type="text"]');
 
  window.clearInitialState = function() {
    chrome.storage.local.set({'newtodo': null});
  }

  window.setInitialState = function() {
    chrome.storage.local.get('newtodo', function(data) {
      if (newTodoInput && data && data.newtodo) {
        newTodoInput.value = data.newtodo;
        newTodoInput.focus();
      }
    });
  };

  var saveTransientState = function() {
    chrome.storage.local.set({'newtodo': newTodoInput.value});
  };

  newTodoInput.addEventListener('keypress' , function() {
    saveTransientState();
  })
    

检查结果

重新加载应用,检查结果:打开应用,单击右键并选择“重新加载应用”。

如果 Chrome 浏览器和应用由于任何原因(而不是用户操作)关闭,则会产生 onRestarted 事件,输入字段中键入的文本(但是还没有保存为待办事项)会在 Chrome 浏览器和应用重新打开时再次出现。

如果您遇到了困难,希望立刻看到应用,请进入 chrome://extensions,载入未打包的 AngularJS 应用 JavaScript 应用,并从新标签页中运行应用。

更多信息

  • 即使当您的窗口都关闭后,事件页面也有可能继续运行。您可以将所有窗口间共享的逻辑移动至事件页面

您还应该阅读

管理应用的生命周期教程

接下来做什么?

6 - 访问用户数据中,您将学习如何认证用户以及如何使用 OAuth2.0 访问 Google 和其他第三方服务。

注意:下一章涉及到的 API 仍然是实验性的,如果您不想尝试实验性 API,您可以跳过,代码实验室的剩余部分不依赖它。