10 dicas de desempenho para apps mobile h bridas · 2014. 8. 27. · 10 dicas de desempenho para...
TRANSCRIPT
Me, Myself && I
!
•Gerente de Desenv Projetos
•8+ XP TI
•Java JUG Leader
•Sencha Community Leader
•http://loiane.com
•@loiane
http://upgrade.ins-us.com/
Nov 2013
I
#1
<div data-role="page" id="tracks">!! <div data-role="header"><h1>Tracks</h1></div>!! <ul data-role="listview">!! <li><a href="getTrackInfo.php?id=1">Desempenho e Escalabilidade na Prática</a></li>!! <li><a href="getTrackInfo.php?id=2">Java na Crista da Onda</a></li>!! <li><a href="getTrackInfo.php?id=3">Arquiteturas que Você Sempre Quis Conhecer</a></li>!! <li><a href="getTrackInfo.php?id=4">Mobile: Portáteis e Furiosos</a></li>!! </ul>!</div>!
<div data-role="page" id="tracks">!! <div data-role="header"><h1>Tracks</h1></div>!! <ul data-role="listview">!! <li><a href="getTrackInfo.php?id=1">Desempenho e Escalabilidade na Prática</a></li>!! <li><a href="getTrackInfo.php?id=2">Java na Crista da Onda</a></li>!! <li><a href="getTrackInfo.php?id=3">Arquiteturas que Você Sempre Quis Conhecer</a></li>!! <li><a href="getTrackInfo.php?id=4">Mobile: Portáteis e Furiosos</a></li>!! </ul>!</div>!
NÃO gere páginas no servidor
Web Browser
Dispositivo
JavaScript
Arquivos Imagens/
Documentos
Banco de Dados caching
Web Browser
Dispositivo
Web Server
Java/PHP/Ruby/C#
Arquivos Imagens/
Documentos
Banco de Dados
Backend
http://
Lógica de negócio
JavaScript
Arquivos Imagens/
Documentos
Banco de Dados caching
JSON
#2
// Obtém dados!$.ajax({url: "getTrackInfo.php?id=1"}).done(function(track) {! // Mostra os detalhes - view! $.mobile.changePage($('#track-info'));!});!
// Obtém dados!$.ajax({url: "getTrackInfo.php?id=1"}).done(function(track) {! // Mostra os detalhes - view! $.mobile.changePage($('#track-info'));!});!
//mostra View!$.mobile.changePage($('#track-info'));!!//------------------------------------------------------------------------!!$(document).bind("pagechange", onPageChange);!!function onPageChange(event, data) {!! var toPageId = data.toPage.attr("id");!!! switch (toPageId) {! case 'track-info':! ! ! clearValues();!! ! // Obtém dados!! ! ! $.ajax({url: "getTrackInfo.php?id=1"}).done(function(track) {!! ! ! // Atualiza os detalhes - view!! ! ! $('#trackNome h1').html(track.name);!! ! ! ! $('#trackDesc').val(track.desc);!! ! ! ! $('#trackDia').val(track.dia);!! ! ! ! $('#trackLocal').val(track.local);!! ! ! ! $('#trackHost').val(track.host);!! ! ! });! ! ! ! break;! }!} !
//mostra View!$.mobile.changePage($('#track-info'));!!//------------------------------------------------------------------------!!$(document).bind("pagechange", onPageChange);!!function onPageChange(event, data) {!! var toPageId = data.toPage.attr("id");!!! switch (toPageId) {! case 'track-info':! ! ! clearValues();!! ! // Obtém dados!! ! ! $.ajax({url: "getTrackInfo.php?id=1"}).done(function(track) {!! ! ! // Atualiza os detalhes - view!! ! ! $('#trackNome h1').html(track.name);!! ! ! ! $('#trackDesc').val(track.desc);!! ! ! ! $('#trackDia').val(track.dia);!! ! ! ! $('#trackLocal').val(track.local);!! ! ! ! $('#trackHost').val(track.host);!! ! ! });! ! ! ! break;! }!} !
Ext.define('MyContacts.store.Contacts', {! extend: 'Ext.data.Store',!! requires: [! 'MyContacts.model.Contact',! 'MyContacts.proxy.ContactsProxy'! ],!! config: {! autoLoad: true,! model: 'MyContacts.model.Contact',! storeId: 'Contacts',! proxy: {! type: 'contactstorage'! }! }!});!
Ext.define('MyContacts.store.Contacts', {! extend: 'Ext.data.Store',!! requires: [! 'MyContacts.model.Contact',! 'MyContacts.proxy.ContactsProxy'! ],!! config: {! autoLoad: true,! model: 'MyContacts.model.Contact',! storeId: 'Contacts',! proxy: {! type: 'contactstorage'! }! }!});!
control: {! "contactslist": {! show: 'onListItemPainted'! }!}!!//-------------------------------------!!onListItemPainted: function(view, options) { ! view.getStore().load();!}!
control: {! "contactslist": {! show: 'onListItemPainted'! }!}!!//-------------------------------------!!onListItemPainted: function(view, options) { ! view.getStore().load();!}!
Mostre a view e depois carregue os
dados
#3
Ext.define('MyContacts.view.ContactsPanel', {! extend: 'Ext.Container',! alias: 'widget.contactspanel',!! requires: [! 'MyContacts.view.ContactsList',! 'MyContacts.view.ContactInfo',! 'MyContacts.view.ContactEdit'! ],!! config: {! layout: {! type: 'card'! },! items: [! {! xtype: 'contactslist'! },! {! xtype: 'contactinfo'! },! {! xtype: 'contactedit'! }! ]! }!!});!
Ext.define('MyContacts.view.ContactsPanel', {! extend: 'Ext.Container',! alias: 'widget.contactspanel',!! requires: [! 'MyContacts.view.ContactsList',! 'MyContacts.view.ContactInfo',! 'MyContacts.view.ContactEdit'! ],!! config: {! layout: {! type: 'card'! },! items: [! {! xtype: 'contactslist'! },! {! xtype: 'contactinfo'! },! {! xtype: 'contactedit'! }! ]! }!!});!
Be LAZY
#4
App com lista dos participantes do QCON SP 2014
select count(*) from ParticipantesQCONSP
App com lista dos participantes do QCON SP 2014
select count(*) from ParticipantesQCONSP
== 1000
App com lista dos participantes do QCON SP 2014
select count(*) from ParticipantesQCONSP
== 1000
App com lista dos participantes do QCON SP 2014
É muito dado?
Paging / Paginação
https://github.com/stakbit/jQuery-Mobile-Listview-Pagination-Plugin
http://dcarrith.github.io/jquery.mobile.lazyloader/
$.ajax({url: "listaEstadosBr.php"}).done(function(data) {! estadosBr = data;!});!
$.ajax({url: "listaEstadosBr.php"}).done(function(data) {! estadosBr = data;!});!
Dados Estáticos
LocalStorage SQLite - database Arquivo - JSON
// do a SERVER load, passing a callback function!offlineSyncStore.loadServer(function(){!! // create a new Person record! var person = Ext.create('Person', {! FirstName: 'Joe',! LastName: 'Bloggs',! Email: '[email protected]'! });!! // add it to the store! offlineSyncStore.add(person);!! // sync the store LOCALLY. If autoServerSync is set to true then this will also sync using SERVER proxy! offlineSyncStore.sync();!! // if autoServerSync is false then call SERVER sync manually! offlineSyncStore.syncServer();!!});!
https://market.sencha.com/extensions/ext-ux-offlinesyncstore
// do a SERVER load, passing a callback function!offlineSyncStore.loadServer(function(){!! // create a new Person record! var person = Ext.create('Person', {! FirstName: 'Joe',! LastName: 'Bloggs',! Email: '[email protected]'! });!! // add it to the store! offlineSyncStore.add(person);!! // sync the store LOCALLY. If autoServerSync is set to true then this will also sync using SERVER proxy! offlineSyncStore.sync();!! // if autoServerSync is false then call SERVER sync manually! offlineSyncStore.syncServer();!!});!
https://market.sencha.com/extensions/ext-ux-offlinesyncstore
Faça cache dos dados
#5
var timeTouch;!!$("body").on("touchend", ".needsclick", function() {! timeTouch = new Date().getTime();!});!!$("body").on("click", ".needsclick", function() {! if (timeTouch) {! $("#log-slow").html("click: " + (new Date().getTime() - timeTouch) + "ms");! }! return false;!});!
var timeTouch;!!$("body").on("touchend", ".needsclick", function() {! timeTouch = new Date().getTime();!});!!$("body").on("click", ".needsclick", function() {! if (timeTouch) {! $("#log-slow").html("click: " + (new Date().getTime() - timeTouch) + "ms");! }! return false;!});!
Evite CLICK use TOUCHEND
Fastclick
https://github.com/ftlabs/fastclick
$("body").on("touchend", ".fastclick", function() {! timeTouch = new Date().getTime();!});!!$("body").on("click", ".fastclick", function() {! if (timeTouch) {! $("#log-fast").html("touchend: " + (new Date().getTime() - timeTouch) + "ms");! } else {! alert("Execute esse exemplo em um device touch");! }! return false;!});!
$("body").on("touchend", ".fastclick", function() {! timeTouch = new Date().getTime();!});!!$("body").on("click", ".fastclick", function() {! if (timeTouch) {! $("#log-fast").html("touchend: " + (new Date().getTime() - timeTouch) + "ms");! } else {! alert("Execute esse exemplo em um device touch");! }! return false;!});!
#6
$("#page").animate();!
$("#page").animate();!
.page {! position: absolute;! width: 200px;! height:200px;! top:20px;! left:50;!}!!.page-left {! left: 50px;!}!.page-center {! left: 275px;!}!.page-right {! left: 500px;!}!!.transition {! transition-duration: .25s;!}!
.page {! position: absolute;! width: 200px;! height:200px;! top:20px;! left:50;!}!!.page-left {! left: 50px;!}!.page-center {! left: 275px;!}!.page-right {! left: 500px;!}!!.transition {! transition-duration: .25s;!}!
Use CSS 3 Transitions +
Hardware Acceleration
.page {! position: absolute;! width: 200px;! height:200px;! top:20px;! left:50;! transform: translate3d(0,0,0);!}!!.page-left {! -webkit-transform: translate3d(30px, 0, 0);! transform: translate3d(31px, 0, 0);!}!.page-center {! -webkit-transform: translate3d(250px, 0, 0);! transform: translate3d(251px, 0, 0);!}!.page-right {! -webkit-transform: translate3d(470px, 0, 0);! transform: translate3d(471px, 0, 0);!}!!.transition {! -webkit-transition-duration: .25s;! transition-duration: .25s;!}!
.page {! position: absolute;! width: 200px;! height:200px;! top:20px;! left:50;! transform: translate3d(0,0,0);!}!!.page-left {! -webkit-transform: translate3d(30px, 0, 0);! transform: translate3d(31px, 0, 0);!}!.page-center {! -webkit-transform: translate3d(250px, 0, 0);! transform: translate3d(251px, 0, 0);!}!.page-right {! -webkit-transform: translate3d(470px, 0, 0);! transform: translate3d(471px, 0, 0);!}!!.transition {! -webkit-transition-duration: .25s;! transition-duration: .25s;!}!
Page Slider
https://github.com/ccoenraets/PageSlider
#7
• box-shadow • border-radius • gradients • text-align
• box-shadow • border-radius • gradients • text-align
Evite sombras e gradientes
#8
$("#contato-info a.back").on("touchend", clickHandler);!$("#contato-info a.back").attr("href", "#contato-info");!$("#contato-info a.back").css("color", "green");!$("#contato-info a.back").css("text-decoration", "none");!
$("#contato-info a.back").on("touchend", clickHandler);!$("#contato-info a.back").attr("href", "#contato-info");!$("#contato-info a.back").css("color", "green");!$("#contato-info a.back").css("text-decoration", "none");!
Ext.ComponentQuery.query('contactinfo button#back')[0].on('tap', clickHandler);!Ext.ComponentQuery.query('contactinfo button#back')[0].setCls('backBtn');!Ext.ComponentQuery.query('contactinfo button#back')[0].setLabelCls('labelCls');!
Ext.ComponentQuery.query('contactinfo button#back')[0].on('tap', clickHandler);!Ext.ComponentQuery.query('contactinfo button#back')[0].setCls('backBtn');!Ext.ComponentQuery.query('contactinfo button#back')[0].setLabelCls('labelCls');!
var $backBtn = $('#contato-info a.back');!$backBtn.on("touchend", clickHandler);!$backBtn.attr("href", "#contato-info");!$backBtn.css("color", "green");!$backBtn.css("text-decoration", "none");!
var $backBtn = $('#contato-info a.back');!$backBtn.on("touchend", clickHandler);!$backBtn.attr("href", "#contato-info");!$backBtn.css("color", "green");!$backBtn.css("text-decoration", "none");!
var backBtn = Ext.ComponentQuery.query('contactinfo button#back')[0];!backBtn.on('tap', clickHandler);!backBtn.setCls('backBtn');!backBtn.setLabelCls('labelCls');!
var backBtn = Ext.ComponentQuery.query('contactinfo button#back')[0];!backBtn.on('tap', clickHandler);!backBtn.setCls('backBtn');!backBtn.setLabelCls('labelCls');!
Minimize Browser Reflows
#9
XUI
x$(document).on("deviceready", function () {!! headingDiv = x$("#heading");! navigator.compass.getCurrentHeading(onSuccess, onError);! navigator.compass.watchHeading(onSuccess, onError, {frequency: 100});!! function onSuccess(heading) {! headingDiv.html(! 'Heading: ' + heading.magneticHeading + '° ' +! convertToText(heading.magneticHeading) + '<br />' +! 'True Heading: ' + heading.trueHeading + '<br />' +! 'Accuracy: ' + heading.headingAccuracy! );! ! // Alter the CSS properties to rotate the rose image! x$(".rose").css({! "-webkit-transform":! "rotate(-" + heading.magneticHeading + "deg)",! "transform":! "rotate(-" + heading.magneticHeading + "deg)"! });! }!! function onError() {! headingDiv.html(! 'There was an error trying to ' +! 'locate your current bearing.'! );! }!});!
Topcoat
Cuidado com framework / lib da
moda
#10
.icon-user {! background-image: url(../images/user.png) !important;!}!!.icon-user-add {! background-image: url(../images/user_add.gif) !important;!}!!.icon-save {! background-image: url(../images/save.gif) !important;!}!!.icon-reset {! background-image: url(../images/stop.png) !important;!}!!.icon-grid {! background-image: url(../images/grid.png) !important;!}!!.icon-add {! background-image: url(../images/add.png) !important;!}!!.icon-delete {! background-image: url(../images/delete.png) !important;!}!
.icon-user {! background-image: url(../images/user.png) !important;!}!!.icon-user-add {! background-image: url(../images/user_add.gif) !important;!}!!.icon-save {! background-image: url(../images/save.gif) !important;!}!!.icon-reset {! background-image: url(../images/stop.png) !important;!}!!.icon-grid {! background-image: url(../images/grid.png) !important;!}!!.icon-add {! background-image: url(../images/add.png) !important;!}!!.icon-delete {! background-image: url(../images/delete.png) !important;!}!
.icon {!! background-image:url(result.png);!}!!.icon-user {! background-position: 0px -156px;!}!!.icon-user-add {! background-position: 0px -130px;!}!!.icon-save {! background-position: 0px -78px;!}!!.icon-reset {! background-position: 0px -104px;!}!!.icon-grid {! background-position: 0px -52px;!}!!.icon-add {! background-position: 0px 0px;!}!!.icon-delete {! background-position: 0px -26px;!}!
.icon {!! background-image:url(result.png);!}!!.icon-user {! background-position: 0px -156px;!}!!.icon-user-add {! background-position: 0px -130px;!}!!.icon-save {! background-position: 0px -78px;!}!!.icon-reset {! background-position: 0px -104px;!}!!.icon-grid {! background-position: 0px -52px;!}!!.icon-add {! background-position: 0px 0px;!}!!.icon-delete {! background-position: 0px -26px;!}!
Build Otimizado
Agrega Valor!
http://jquerymobile.com/download-builder/
http://jquerymobile.com/download-builder/
OTIMIZE JS, CSS, HTML
http://browserdiet.com/pt/
https://github.com/loiane/mobile-hibrido-performance
http://loiane.com
facebook.com/loianegroner
@loiane
https://github.com/loiane
youtube.com/user/Loianeg
Obrigada!