Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 <h1 id="lab_6_lifecycle">Lab 6 - Lifecycle</h1> | 1 <h1 id="lab_6_lifecycle">Manage App Lifecycle</h1> |
| 2 | 2 |
| 3 <p>Like everything in this world, apps have a lifecycle. They are installed, la unched, restarted, suspended when the system needs to free up resources and unin stalled. This lab will show you the basics of the Chrome app lifecycle and how its heart, the event page (aka background script), is used.</p> | 3 <p>Like everything in this world, apps have a lifecycle. |
| 4 | 4 They are installed, launched, restarted, suspended when the system needs to free up resources and uninstalled. |
| 5 <h2 id="you_should_also_read">You should also read</h2> | 5 This lab will show you the basics of the Chrome packaged app lifecycle and |
| 6 | 6 how its heart, the event page (aka background script), is used.</p> |
| 7 <p><a href="http://developer.chrome.com/apps/app_lifecycle.html">Manage App Life cycle</a> in Chrome app docs</p> | |
| 8 | 7 |
| 9 <h2 id="the_event_page">The event page</h2> | 8 <h2 id="the_event_page">The event page</h2> |
|
Renato Mangini (chromium)
2013/04/09 17:32:32
Background page is another commonly used name. Sho
mkearney1
2013/04/10 17:59:58
Above, I've said 'aka background script' for event
| |
| 10 | 9 |
| 11 <p>The event page is one of the most important pieces of a Chrome app. It's responsible for what gets launched, when, and how. | 10 <p>The event page is one of the most important pieces of a Chrome packaged app. |
| 12 For example, if your app is an instant messenger, you might want your event page to only show a UI when there is a new notification.</p> | 11 It's responsible for what gets launched, when, and how. |
| 12 For example, if your app is an instant messenger, | |
| 13 you might want your event page to only show a UI when there is a new notificatio n.</p> | |
| 13 | 14 |
| 14 <p>For simpler apps, the event page listens to the app lifecycle events and reac ts appropriately. | 15 <p>For simpler apps, the event page listens to the app lifecycle events and reac ts appropriately. |
| 15 There are two important lifecycle events, $ref:app.runtime.onLaunched and $ref:a pp.runtime.onRestarted.</p> | 16 There are two important lifecycle events, $ref:app.runtime.onLaunched and $ref:a pp.runtime.onRestarted.</p> |
| 16 | 17 |
| 17 <h2 id="the_onlaunched_event_and_the_chrome_app_window_create_method">The onLaun ched event and the chrome.app.window.create method</h2> | 18 <h2 id="the_onlaunched">The onLaunched event</h2> |
| 18 | 19 |
| 19 <p>$ref:app.runtime.onLaunched is the most important event. It fires when the us er clicks on your app's icon with the intent of launching it. For most simpl er apps, the event page will listen for this event and open a window when it fir es. See our <a href="https://github.com/GoogleChrome/chrome-app-codelab/blob/mas ter/lab6_lifecycle/angularjs/main.js">main.js</a> for the most common usage.</p> | 20 <p>The $ref:app.runtime.onLaunched event is the most important event. |
| 21 It fires when the user clicks on your app's icon with the intent of launchin g it. | |
| 22 For most simpler apps, | |
| 23 the event page will listen for this event and open a window when it fires. | |
| 24 See | |
| 25 <a href="https://github.com/GoogleChrome/chrome-app-codelab/blob/master/lab6_lif ecycle/angularjs/main.js">AngularJS main.js</a> or | |
| 26 <a href="https://github.com/GoogleChrome/chrome-app-codelab/blob/master/lab6_lif ecycle/javascript/main.js">JavaScript main.js</a> | |
| 27 for the most common usage.</p> | |
| 20 | 28 |
| 21 <h3 id="windows_with_ids">Windows with IDs</h3> | 29 <h3 id="windows_with_ids">Windows with IDs</h3> |
| 22 | 30 |
| 23 <p>The $ref:app.window.create method can associate an ID to the window being ope ned. Currently, the most interesting use for this is to restore a window's w idth, height and location and its associated Developer Tools window, if opened, when the app is launched. </p> | 31 <p>The $ref:app.window.create method can associate an ID to the window being ope ned. Currently, the most interesting use for this is to restore a window's w idth, height and location and its associated Developer Tools window, if opened, when the app is launched. </p> |
| 24 | 32 |
| 25 <p>Execute your app as it is now, move and resize the window, close and restart it. The app will reopen in the original location, right? Now add a property <cod e>id</code> to the <a href="https://github.com/GoogleChrome/chrome-app-codelab/b lob/master/lab6_lifecycle/angularjs/main.js">main.js</a>, reload the app and tes t again:</p> | 33 <p>Execute your app as it is now, move and resize the window, |
| 34 close and restart it. | |
| 35 The app will reopen in the original location, right? | |
| 36 Now add a property <code>id</code> to the event page, | |
| 37 <a href="https://github.com/GoogleChrome/chrome-app-codelab/blob/master/lab6_lif ecycle/angularjs/main.js">Angular main.js</a> or | |
| 38 <a href="https://github.com/GoogleChrome/chrome-app-codelab/blob/master/lab6_lif ecycle/javascript/main.js">JavaScript main.js</a>, | |
| 39 reload the app and test again:</p> | |
| 26 | 40 |
| 27 <pre><code><pre> | 41 <pre> |
| 28 chrome.app.runtime.onLaunched.addListener(function() { | 42 chrome.app.runtime.onLaunched.addListener(function() { |
| 29 chrome.app.window.create('index.html', | 43 chrome.app.window.create('index.html', |
| 30 {id: 'mainwindow', bounds: {width: 500, height: 309} }); | 44 {id: 'mainwindow', bounds: {width: 500, height: 309} }); |
| 31 }); | 45 }); |
| 32 </pre></code></pre> | 46 </pre> |
| 33 | 47 |
| 34 <p>If your application requires, you can open more than one window.</p> | 48 <p>If your application requires, you can open more than one window.</p> |
| 35 | 49 |
| 36 <h2 id="the_onrestarted_event">The onRestarted event</h2> | 50 <h2 id="the_onrestarted_event">The onRestarted event</h2> |
| 37 | 51 |
| 38 <p>The $ref:app.runtime.onRestarted event is not as essential as <code>onLaunche d</code>, but it might be relevant to certain types of apps. | 52 <p>The $ref:app.runtime.onRestarted event is not as essential as <code>onLaunche d</code>, |
| 39 This event is executed when the app is restarted, for example, when Chrome quits , restarts, and the app is launched again. | 53 but it might be relevant to certain types of apps. |
| 40 You can use this event to restore a transient state. </p> | 54 This event is executed when the app is restarted, for example, |
| 55 when Chrome quits, restarts, and the app is launched again. | |
| 56 You can use this event to restore a transient state.</p> | |
| 41 | 57 |
| 42 <p>For example, if your app has a form with several fields, you won't always want to save the partial form while the user is typing. | 58 <p>For example, if your app has a form with several fields, |
| 59 you won't always want to save the partial form while the user is typing. | |
| 43 If the user quits the app on purpose, she might not be interested keeping the pa rtial data. | 60 If the user quits the app on purpose, she might not be interested keeping the pa rtial data. |
| 44 If the Chrome runtime restarted for some reason other than by a user's inten tion, the user will want that data when the app is restarted.</p> | 61 If the Chrome runtime restarted for some reason other than by a user's inten tion, |
| 62 the user will want that data when the app is restarted.</p> | |
| 45 | 63 |
| 46 <p>Let's change our code to save the Todo input field in $ref:storage as the user types, only restoring it if the <code>onRestarted</code> event is triggere d.</p> | 64 <p>Let's change our code to save the Todo input field in $ref:storage as the user types, |
| 65 only restoring it if the <code>onRestarted</code> event is triggered.</p> | |
| 47 | 66 |
| 48 <p class="note"><b>Note:</b> We learned about <code>chrome.storage.sync</code> before, but <a href="http://developer.chrome.com/trunk/apps/storage.html#using-s ync">chrome.storage.local</a> wasn't mentioned until now. Both have exactly the same syntax, but the semantics of <code>chrome.storage.local</code> is, as t he name says, completely local. | 67 <p class="note"><b>Note:</b> |
| 68 We learned about <code>chrome.storage.sync</code> before, but | |
| 69 <a href="http://developer.chrome.com/trunk/apps/storage.html#using-sync">chrome. storage.local</a> | |
| 70 wasn't mentioned until now. | |
| 71 Both have exactly the same syntax, | |
| 72 but the semantics of <code>chrome.storage.local</code> is, as the name says, com pletely local. | |
| 49 There's no attempt to synchronize or to save the data in the cloud.</p> | 73 There's no attempt to synchronize or to save the data in the cloud.</p> |
| 50 | 74 |
| 51 <ul> | 75 <h3 id="event-page">Update event page</h3> |
| 52 <li>Event page: <a href="https://github.com/GoogleChrome/chrome-app-codelab/blob /master/lab6_lifecycle/angularjs/main.js">main.js</a> | 76 |
| 77 <p>Update the event page to include the | |
| 78 <code>onLaunched</code> and <code>onRestarted</code> events. | |
| 79 Events are handled the same in | |
| 80 <a href="https://github.com/GoogleChrome/chrome-app-codelab/blob/master/lab6_lif ecycle/angularjs/main.js">AngularJS main.js</a> and | |
| 81 <a href="https://github.com/GoogleChrome/chrome-app-codelab/blob/master/lab6_lif ecycle/javascript/main.js">JavaScript main.js</a>: | |
| 82 </p> | |
| 83 | |
| 53 <pre> | 84 <pre> |
| 54 chrome.app.runtime.onLaunched.addListener(function() { | 85 chrome.app.runtime.onLaunched.addListener(function() { |
| 55 // normal launch initiated by the user, let's start clean. | 86 // normal launch initiated by the user, let's start clean. |
| 56 // note that this is not related to the persistent state, which is | 87 // note that this is not related to the persistent state, which is |
| 57 // appropriately handled in the window code. | 88 // appropriately handled in the window code. |
| 58 runApp(false); | 89 runApp(false); |
| 59 }); | 90 }); |
| 60 | 91 |
| 61 chrome.app.runtime.onRestarted.addListener(function() { | 92 chrome.app.runtime.onRestarted.addListener(function() { |
| 62 // if restarted, try to get the transient saved state | 93 // if restarted, try to get the transient saved state |
| 63 runApp(true); | 94 runApp(true); |
| 64 }); | 95 }); |
| 65 | 96 |
| 66 function runApp(readInitialState) { | 97 function runApp(readInitialState) { |
| 67 chrome.app.window.create('index.html', | 98 chrome.app.window.create('index.html', |
| 68 {id: 'mainwindow', bounds: {width: 500, height: 309} }, | 99 {id: 'mainwindow', bounds: {width: 500, height: 309} }, |
| 69 // the create callback gets a reference to the AppWindow obj | 100 // the create callback gets a reference to the AppWindow obj |
| 70 function(win) { | 101 function(win) { |
| 71 // when the callback is executed, the DOM is loaded but no script was | 102 // when the callback is executed, the DOM is loaded but no script was |
| 72 // loaded yet. So, let's attach to the load event. | 103 // loaded yet. So, let's attach to the load event. |
| 73 win.contentWindow.addEventListener('load', function() { | 104 win.contentWindow.addEventListener('load', function() { |
| 74 if (readInitialState) { | 105 if (readInitialState) { |
| 75 win.contentWindow.setInitialState(); | 106 win.contentWindow.setInitialState(); |
| 76 } else { | 107 } else { |
| 77 win.contentWindow.clearInitialState(); | 108 win.contentWindow.clearInitialState(); |
| 78 } | 109 } |
| 79 }); | 110 }); |
| 80 }); | 111 }); |
| 81 } | 112 } |
| 82 </pre></li><li>Controller: add to existing <a href="https://github.com/GoogleChr ome/chrome-app-codelab/blob/master/lab6_lifecycle/angularjs/controller.js">contr oller.js</a> | 113 </pre> |
| 83 <pre> | 114 |
| 115 <h3 id="controller">Update controller</h3> | |
| 116 | |
| 117 <p>Add to existing | |
| 118 <a href="https://github.com/GoogleChrome/chrome-app-codelab/blob/master/lab6_lif ecycle/angularjs/controller.js">AngularJS controller.js</a> or | |
| 119 <a href="https://github.com/GoogleChrome/chrome-app-codelab/blob/master/lab6_lif ecycle/javascript/controller.js">JavaScript controller.js</a>: | |
| 120 </p> | |
| 121 | |
| 122 <tabs data-group="source"> | |
| 123 | |
| 124 <header tabindex="0" data-value="angular">Angular</header> | |
| 125 <header tabindex="0" data-value="js">JavaScript</header> | |
| 126 | |
| 127 <content> | |
| 128 <pre> | |
| 84 var newTodoInput = null; | 129 var newTodoInput = null; |
| 85 | 130 |
| 86 var clearInitialState = function() { | 131 var clearInitialState = function() { |
| 87 chrome.storage.local.set({'newtodo': null}); | 132 chrome.storage.local.set({'newtodo': null}); |
| 88 } | 133 } |
| 89 | 134 |
| 90 var setInitialState = function() { | 135 var setInitialState = function() { |
| 91 chrome.storage.local.get('newtodo', function(data) { | 136 chrome.storage.local.get('newtodo', function(data) { |
| 92 if (newTodoInput && data && data.newtodo) { | 137 if (newTodoInput && data && data.newtodo) { |
| 93 newTodoInput.value = data.newtodo; | 138 newTodoInput.value = data.newtodo; |
| 94 newTodoInput.focus(); | 139 newTodoInput.focus(); |
| 95 } | 140 } |
| 96 }); | 141 }); |
| 97 } | 142 } |
| 98 | 143 |
| 99 window.addEventListener('load', function() { | 144 window.addEventListener('load', function() { |
| 100 var saveTransientState = function() { | 145 var saveTransientState = function() { |
| 101 chrome.storage.local.set({'newtodo': newTodoInput.value}); | 146 chrome.storage.local.set({'newtodo': newTodoInput.value}); |
| 102 }; | 147 }; |
| 103 newTodoInput = document.querySelector('input[type="text"]'); | 148 newTodoInput = document.querySelector('input[type="text"]'); |
| 104 newTodoInput.addEventListener('keypress' , function() { | 149 newTodoInput.addEventListener('keypress' , function() { |
| 105 saveTransientState();<br> | 150 saveTransientState();<br> |
| 106 }) | 151 }) |
| 107 }) | 152 }) |
| 108 </pre></p></li><li><p>Save the changes by reloading the app: open the app, right -click and select Reload.</p></li> | 153 </pre> |
| 154 </content> | |
| 155 <content> | |
| 156 <pre> | |
| 157 var newTodoInput = document.querySelector('input[type="text"]'); | |
| 158 | |
| 159 window.clearInitialState = function() { | |
| 160 chrome.storage.local.set({'newtodo': null}); | |
| 161 } | |
| 162 | |
| 163 window.setInitialState = function() { | |
| 164 chrome.storage.local.get('newtodo', function(data) { | |
| 165 if (newTodoInput && data && data.newtodo) { | |
| 166 newTodoInput.value = data.newtodo; | |
| 167 newTodoInput.focus(); | |
| 168 } | |
| 169 }); | |
| 170 }; | |
| 171 | |
| 172 var saveTransientState = function() { | |
| 173 chrome.storage.local.set({'newtodo': newTodoInput.value}); | |
| 174 }; | |
| 175 | |
| 176 newTodoInput.addEventListener('keypress' , function() { | |
| 177 saveTransientState(); | |
| 178 }) | |
| 179 </pre> | |
| 180 | |
| 181 </tabs> | |
| 182 | |
| 183 <h3 id="results">Check the results</h3> | |
| 184 | |
| 185 <p>Save the changes by reloading the app: | |
| 186 open the app, right-click and select Reload.</p> | |
| 187 | |
| 188 <p>If Chrome and the app shuts down for any reason (other than a user-gesture), | |
| 189 the <code>onRestarted</code> event is fired. | |
| 190 Any text entered in the input field (but not yet saved as a Todo item) | |
| 191 will reappear when Chrome and the app are reopened.</p> | |
| 192 | |
| 193 <p>If you get stuck and want to see the app in action, | |
| 194 go to <code>chrome://extensions</code>, | |
| 195 load the unpacked | |
| 196 <a href="https://github.com/GoogleChrome/chrome-app-codelab/tree/master/lab6_lif ecycle/angularjs">AngularJS app</a> or | |
| 197 <a href="https://github.com/GoogleChrome/chrome-app-codelab/tree/master/lab6_lif ecycle/javascript">JavaScript app</a>, | |
| 198 and launch the app from a new tab.</p> | |
| 199 | |
| 200 <h2 id="takeaways_">Takeaways</h2> | |
| 201 | |
| 202 <ul> | |
| 203 <li>The event page may continue to run even when your windows are closed; | |
| 204 you can move logic that is shared amoung windows to the event page.</li> | |
| 109 </ul> | 205 </ul> |
| 110 | 206 |
| 111 <p>If Chrome and the app shuts down for any reason (other than a user-gesture), the <code>onRestarted</code> event is fired. | 207 <h2 id="you_should_also_read">You should also read</h2> |
| 112 Any text entered in the input field (but not yet saved as a Todo item) will reap pear when Chrome and the app are reopened.</p> | |
| 113 | 208 |
| 114 <p class="note"><b>Note:</b> If you get stuck and want to see the app in action , go to <code>chrome://extensions</code>, | 209 <p><a href="http://developer.chrome.com/apps/app_lifecycle.html">Manage App Life cycle</a> tutorial</p> |
| 115 load the unpacked <a href="https://github.com/GoogleChrome/chrome-app-codelab/tr ee/master/lab6_lifecycle">lab6 app</a>, and launch the app from a new tab.</p> | |
| 116 | 210 |
| 117 <h1 id="takeaways_">Takeaways:</h1> | 211 <h2 id="what_39_s_next_">What's next?</h2> |
| 118 | 212 |
| 119 <ul> | 213 <p>In <a href="app_codelab7_useridentification.html">6 - Access User's Data</a>, |
| 120 <li>The event page may continue to run even when your windows are closed. You ca n move logic that is shared among windows to the event page, as we will see in < a href="app_codelab9_multipleviews.html">lab9</a>.</li> | |
| 121 </ul> | |
| 122 | |
| 123 <h1 id="what_39_s_next_">What's next?</h1> | |
| 124 | |
| 125 <p>In <a href="app_codelab7_useridentification.html">lab7_useridentification</a> , | |
| 126 you will learn how to identify users and use OAuth2.0 to access Google and other third party services.</p> | 214 you will learn how to identify users and use OAuth2.0 to access Google and other third party services.</p> |
| 127 | 215 |
| 128 <p class="note"><b>Note:</b> The <a href="http://developer.chrome.com/trunk/app s/app_identity.html">identify API</a> covered in lab 7 is still experimental.</p > | 216 <p class="note"><b>Note:</b> |
| 217 The <a href="http://developer.chrome.com/trunk/apps/app_identity.html">identify API</a> covered in lab 7 is still experimental.</p> | |
|
Renato Mangini (chromium)
2013/04/09 17:32:32
change text to something like "The next chapter co
mkearney1
2013/04/10 17:59:58
Done.
| |
| OLD | NEW |