46
Titanium Beginning Best Practices

TiConf 2014 - Titanium Best Practices, memory management

Embed Size (px)

DESCRIPTION

Many people that come to Titanium and Alloy come to it from a background in web development. Having that as a background is great but often times it is lacking in some basic disciplines that are important for success. Success not only in the initial development but also the long term maintenance and upkeep of the app you are building. When working with frameworks like Titanium or Node.js, it?s easy to have a fire and forget mentality. These frameworks make it so simple to get to ?hello world? that sometimes we forget how important best practices are. In this session I will take you through some of the beginning best practices that have helped me maintain thousands of apps and tens of thousands of lines of code. I have made a lot of mistakes and will try to help you avoid as many of those pitfalls as possible. This session will be specifically geared for the person that is relatively new to Titanium and/or Alloy and will address things like application structure for Classic and Alloy based applications. The plan is to answer questions like, why is my app leaking, how to I manage memory, how and when do I use a window vs. a view? What does it mean to open a window with a different context? How do I use commonJS modules effectively? What is a global event listener and why do people tell me not to use them? How do I get help, and why won?t anyone answer my questions in the support forums? If you want to love working with Titanium for a long time to come, check out some of the best practices that will help you get there.

Citation preview

  • Titanium Beginning Best Practices
  • A little about me. Josh Jensen mashstack.com
  • Beginning Best Practices& Goal: To help you keep your WTF/min to a minimum.
  • Beginning Best Practices& Best Practices > General Javascript Topics We all know Javascript has its quirks, but it is a powerful, expressive language that allows us to do amazing things.
  • A couple of great books to read. Beginning Best Practices& Best Practices > General Javascript Topics
  • Beginning Best Practices& Best Practices > General Javascript Topics Reminder: ! Many of these are personal preferences.
  • JSHint Beginning Best Practices& Best Practices > General Javascript Topics http://www.jshint.com/
  • My preferred style guide Beginning Best Practices& Best Practices > General Javascript Topics https://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml
  • Ti. vs. Titanium. namespace Beginning Best Practices& Best Practices > General Titanium Topics Remember: When typing out the namespace, if you snicker you have gone too far, remove the t var win = Ti.UI.createWindow({}); // vs. var win = Titanium.UI.createWindow({});
  • Opening a Window Beginning Best Practices& Best Practices > General Titanium Topics Avoid using the url property when creating a window. // No, no, no var win = Ti.UI.createWindow({ url: windows/window.js }); // Yes var win = Titanium.UI.createWindow({});
  • A Classic Folder Structure Beginning Best Practices& Best Practices > General Titanium Topics Your folder structure needs to make as much sense as your code. Remember that you are doing this for future you or someone else. - Resources - android - app.js - application - application.js - ui - helpers - lib - iphone ! ! Create an application folder for all of your Titanium code.
  • Windows vs. Views Beginning Best Practices& Best Practices > General Titanium Topics Its up to you! Kind of.
  • CommonJS Beginning Best Practices& Bringing sanity to your project. Best Practices > CommonJS
  • What is CommonJS? Beginning Best Practices& A simple API for declaring modules. Best Practices > CommonJS
  • Some things to know about CommonJS Beginning Best Practices& Best Practices > CommonJS
  • What does a CommonJS module look like? Beginning Best Practices& Best Practices > CommonJS // Private var count = 0; // Public exports.incrementCount = function() { count = count + 1; return count; };
  • What does a CommonJS module look like? Beginning Best Practices& Best Practices > CommonJS // require var libA = require("lib/liba"); // exports exports.createInstance = function() { };
  • exports. vs. module.exports Beginning Best Practices& Best Practices > CommonJS // module.exports var instanceFactory = {}; instanceFactory.createInstance = function() { }; module.exports = instanceFactory; exports.createInstance = function() { };
  • Simple CommonJS App Example Beginning Best Practices& Best Practices > CommonJS var APP = require("application/application"); APP.init(); var APP = {}; ! APP.init = function() { var win = Ti.UI.createWindow({ backgroundColor: "#fff" }); ! var label = Ti.UI.createLabel({ color: "#333", text: "Hello TiConf", font: { fontSize:20, fontFamily: "Helvetica Neue" }, textAlign: "center", width: "auto" }); win.add(label); ! win.open(); }; ! module.exports = APP; app.js application/application.js
  • Best Practices > CommonJS var APP = require("application/application"); APP.init(); var social = require("dk.napp.social"); ! var uiHelper = require("application/helpers/ui"); ! var APP = {}; ! APP.init = function() { var win = uiHelper.windowFactory({ backgroundColor: "#fff" }, { onClose: function() { win = null; label = null; } }); ! var label = uiHelper.labelFactory({ text: "Hello TiConf" }); win.add(label); ! win.open(); }; ! module.exports = APP; app.js application/application.js var _ = require("application/vendor/underscore"); ! exports.windowFactory = function(_params, _listeners) { var win = Ti.UI.createWindow(_.extend(_params, {})); ! var onWindowClose = function() { Ti.API.info("Window Closed"); if (_listeners.onClose) { _listeners.onClose(); } win = null; onWindowClose = null; }; ! win.addEventListener("close", onWindowClose); return win; }; ! exports.labelFactory = function(_params) { var label = Ti.UI.createLabel(_.extend(_params, { color: "#333", font: { fontSize:20, fontFamily: "Helvetica Neue" }, textAlign: "center", width: "auto" })); ! return label; }; application/helpers/ui.js
  • CommonJS can be used to share data in the application. Beginning Best Practices& Best Practices > CommonJS
  • Using Native Modules Beginning Best Practices& Best Practices > CommonJS var social = require("dk.napp.social"); app.js dk.napp.social tiapp.xml $ gittio install dk.napp.social [sudo] npm install -g gittio Check out http://gitt.io
  • Formatting style preference Beginning Best Practices& Best Practices > CommonJS var social = require("dk.napp.social"); ! var uiHelper = require("application/helpers/ui"); ! var APP = {}; application/application.js Note: This is a style preference Not law. Installed Modules (Referenced in tiapp.xml) Local CommonJS Modules Declared Variables
  • Memory management Beginning Best Practices& Best Practices > Memory Management
  • Memory Management Beginning Best Practices& Best Practices > Memory Management Titanium Native Kroll Bridge Windows, Buttons, Views, etc.
  • Memory Management Beginning Best Practices& Best Practices > Memory Management exports.windowFactory = function(_params, _listeners) { var win = Ti.UI.createWindow(_.extend(_params, {})); ! var onWindowClose = function() { Ti.API.info("Window Closed"); if (_listeners.onClose) { _listeners.onClose(); } win = null; onWindowClose = null; }; ! win.addEventListener("close", onWindowClose); return win; }; Remember: If in doubt, null it out var win = uiHelper.windowFactory({ backgroundColor: "#fff" }, { onClose: function() { win = null; label = null; } }); application/application.js application/helpers/ui.js
  • Beginning Best Practices& Best Practices > Memory Management for (var i = 0; i < 5; i++) { var star = Ti.UI.createImageView({ height:'44dp', width:'44dp', top: "50dp", left:'10dp', backgroundColor: "#333" }); (function() { var index = i; star.addEventListener('click', function() { setRating(index+1); }); })(); myView.add(star); } Possible memory leaks http://www.tidev.io/2014/03/27/memory-management/
  • Beginning Best Practices& Best Practices > Memory Management var starWrapper = Ti.UI.createView({ layout: "horizontal", top: "10dp", width: "145dp", height: "24dp" }); ! win.add(starWrapper); ! for (var i = 0; i < 6; i++) { starWrapper.add(Ti.UI.createImageView({ id: "star" + i, height: "24dp", width: "24dp", left: "5dp", image: "/images/star.png", opacity: 0.5 })); } ! var onStarTap = function(e) { _.each(starWrapper.getChildren(), function(child) { child.setOpacity(0.5); }); e.source.setOpacity(1); setRating(e.source.id); Ti.API.info(currentRating); }; ! starWrapper.addEventListener("click", onStarTap); A better way No reference to createImage has been stored. We are not adding an eventListener to each imageView
  • Beginning Best Practices& Best Practices > Memory Management // Global system Events Ti.Network.addEventListener("change", APP.networkObserver); Ti.Gesture.addEventListener("orientationchange", APP.orientationObserver); Ti.App.addEventListener("pause", APP.exitObserver); Ti.App.addEventListener("close", APP.exitObserver); Ti.App.addEventListener("resumed", APP.resumeObserver); ! if(OS_ANDROID) { APP.MainWindow.addEventListener("androidback", APP.backButtonObserver); } Global Event Listeners
  • Checking your memory management Beginning Best Practices& Best Practices > Memory Management $ titanium build --platform ios --target simulator --sim-type iphone --tall --retina Build your project for the simulator 1 Go to your project folder > build > iPhone > Click on the Xcode project le. 2
  • Checking your memory management Beginning Best Practices& Best Practices > Memory Management Open Xcode: Select: Product > Destination > iPhone Retina (4-inch) Then select an OS version, like 7.1 3
  • Checking your memory management Beginning Best Practices& Best Practices > Memory Management Then select: Product > Prole4
  • Checking your memory management Beginning Best Practices& Best Practices > Memory Management Wait5
  • Checking your memory management Beginning Best Practices& Best Practices > Memory Management Select: Allocations6
  • Checking your memory management Beginning Best Practices& Best Practices > Memory Management Add TiUI here7 As you use your app in the simulator you will see TiUI items start showing up in your Allocation summary. 8
  • Checking your memory management Beginning Best Practices& Best Practices > Memory Management Add TiUI here
  • Checking your memory management Beginning Best Practices& Best Practices > Memory Management Add TiUI here
  • Memory Management Beginning Best Practices& Best Practices > Memory Management http://www.tidev.io/2014/03/27/memory-management/
  • Beginning Best Practices& Best Practices > Alloy Alloy Highly recommended!
  • Beginning Best Practices& Best Practices > Alloy Alloy is a framework that follows an MVC architecture Whats that? model-view-controller (MVC)
  • Beginning Best Practices& Best Practices > Alloy Alloy specic best practices.I have 3
  • Beginning Best Practices& Best Practices > Alloy Alloy specic best practices. Use it!
  • Beginning Best Practices& Best Practices > Alloy Alloy specic best practices. Use Alloy.Global sparingly Use it, its incredibly powerful, but use it carefully.
  • Beginning Best Practices& Best Practices > Alloy Alloy specic best practices. Dont forget to call $.destroy(); when you are done with a controller. $.win.addEventListener("close", function(){ $.destroy(); }
  • Being a good community member Beginning Best Practices& Best Practices > Community http://bit.ly/appc-qa - Using Questions and Answers Read This Then this Finally, read this before you post something
  • Questions? Beginning Best Practices& Best Practices > General Titanium Topics http://bit.ly/ticonfjosh @joshj Slides/Example app: Twitter: