<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Criteria Studio &#187; tableviews</title>
	<atom:link href="https://www.criteriastudio.com/tag/tableviews/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.criteriastudio.com</link>
	<description>Mobile apps developers</description>
	<lastBuildDate>Wed, 23 May 2018 10:18:22 +0000</lastBuildDate>
	<language>es-ES</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=3.9.40</generator>
	<item>
		<title>Titanium: Tablas y callbacks</title>
		<link>https://www.criteriastudio.com/titanium-tablas-y-callbacks/</link>
		<comments>https://www.criteriastudio.com/titanium-tablas-y-callbacks/#comments</comments>
		<pubDate>Fri, 31 Aug 2012 17:01:23 +0000</pubDate>
		<dc:creator><![CDATA[J. Rayon]]></dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[callback]]></category>
		<category><![CDATA[HTTPClient]]></category>
		<category><![CDATA[tableviews]]></category>
		<category><![CDATA[titanium]]></category>

		<guid isPermaLink="false">http://www.criteriastudio.com/?p=563</guid>
		<description><![CDATA[En el último evento de Titanium, desarrollé un pequeño ejemplo para iOS y Android que consistía en una tabla con imágenes de un feed de flickr. Al pulsar una fila de la tabla se abre una ventana con la foto ampliada. Es un ejemplo sencillo que me permite introducir un par de conceptos sobre Titanium y [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>En el <a href="http://www.criteriastudio.com/summer-workshop-de-titanium-14-agosto-en-becode/">último evento de Titanium</a>, desarrollé un pequeño ejemplo para iOS y Android que consistía en una tabla con imágenes de un <a href="http://www.flickr.com/services/feeds/">feed de flickr</a>. Al pulsar una fila de la tabla se abre una ventana con la foto ampliada. Es un ejemplo sencillo que me permite introducir un par de conceptos sobre Titanium y commonJS.</p>
<p>Primero veremos cómo personalizar objetos de Titanium para posteriormente crear múltiples instancias del mismo. Crearemos nuestro propio módulo commonJS que devuelve un TableViewRow ya personalizado con los datos de cada fila.</p>
<p>En segundo lugar, veremos cómo llamar a un servicio web remoto, cuya respuesta es asíncrona (esto es, no ocurre en el orden normal del hilo de ejecución, si no cuando llega la respuesta del servidor). Para gestionar esta respuesta asíncrona haremos uso de las funciones callback y haré una breve discusión sobre cuándo usar funciones callback y cuando usar eventos a nivel de aplicación, por si a Miguel Ángel no le quedó del todo claro.</p>
<p>Si no has seguido los anteriores posts, te recomiendo echar un vistazo <a href="http://www.criteriastudio.com/category/blog/" target="_blank">al blog con la introducción de JavaScript y commonJS para Titanium</a>.</p>
<p>Como siempre, empezamos con app.js y los módulos de la aplicación declarados en ModulePaths.js. La discusión de estos ficheros es la misma que <a href="http://www.criteriastudio.com/app-template-para-titanium/">hice en esta entrada</a>, así que no la repito.</p>
<h4>App.js</h4>
<p>gist id=3554525 file=app.js]</p>
<h4>ModulePaths.js</h4>
<p>gist id=3554525 file=ModulePaths.js]</p>
<h4>Styles.js</h4>
<p>gist id=3554525 file=Styles.js]</p>
<h4>AppWindow.js</h4>
<p>Esta es la ventana que se crea desde app.js, simplemente añade la tabla de fotos a la ventana y la devuelve para que app.js cree una instancia y la abra.</p>
<p>gist id=3554525 file=AppWindow.js]</p>
<h4>PhotosTableView.js</h4>
<p>Este módulo devuelve un tableView de Titanium, que llama a <code class="codecolorer text mac-classic"><span class="text">Feed.getData</span></code> (que veremos a continuación) y  le pasa como argumento <code class="codecolorer text mac-classic"><span class="text">callbackTableView</span></code>, que es el nombre de una función definida previamente. Feed se conecta con los servicios de Flickr y recibe un listado de fotografías. Si la información que devuelve <code class="codecolorer text mac-classic"><span class="text">Feed.getData</span></code> fuera local (de un fichero o una base de datos), podríamos hacer algo como <code class="codecolorer text mac-classic"><span class="text">tableview.data = Feed.getData()</span></code> (suponiendo que la info viniera ya formateada). Pero como <code class="codecolorer text mac-classic"><span class="text">Feed</span></code> va a conectar con un servidor remoto y no sabemos cuándo va a responder, lo que hacemos es pasarle como argumento la función que queremos que ejecute cuando ya tenga la respuesta del servidor.</p>
<p>De momento, basta saber que cuando <code class="codecolorer text mac-classic"><span class="text">Feed.getData</span></code> termine de hacer lo que tenga que hacer, llamará a <code class="codecolorer text mac-classic"><span class="text">callbackTableView</span></code></p>
<p>gist id=3554525 file=PhotosTableView.js]</p>
<p>Cuando <code class="codecolorer text mac-classic"><span class="text">Feed</span></code> tiene respuesta del servidor, llama a <code class="codecolorer text mac-classic"><span class="text">callbackTableView</span></code> y le pasa como argumento dicha respuesta. Dentro de <code class="codecolorer text mac-classic"><span class="text">callbackTableView</span></code>, si la respuesta es válida, se crean las instancias de <code class="codecolorer text mac-classic"><span class="text">PhotoRow</span></code>, que son cada una de las filas de la tabla. Finalmente se añaden a la tabla.</p>
<p>Después de la función de callback, digo a la tabla que escuche los eventos click que pueda recibir y, si la fila es válida, creará una instancia de <code class="codecolorer text mac-classic"><span class="text">PhotoViewer</span></code> para visualizar la foto en grande. Siempre es mejor añadir el eventListener al tableView y no a las tableViewRow, es más eficiente gestionar un sólo eventListener (uno por la tabla) que decenas o cientos de eventListeners (tantos como filas tenga la tabla). Por tanto, evita la tentación de usar eventListeners a nivel de fila.</p>
<p><code class="codecolorer text mac-classic"><span class="text">e.row</span></code> es el objeto fila que ha sido clickado y Titanium se encarga de devolvérnoslo siempre que se hace click en la tabla. <code class="codecolorer text mac-classic"><span class="text">e.row.data</span></code> es una propiedad creada por nosotros mismos en el módulo PhotoRow. Lo que hago es crear esta propiedad con toda la información del elemento devuelta por el servidor para poderla recuperar más adelante (en el siguiente apartado se termina de entender esto).</p>
<h4>PhotosTableViewRow.js</h4>
<p>Es cada una de las filas de la tabla. Este componente se va a reutilizar varias veces (al contrario que el resto, que sólo se usan una vez en la aplicación). Para hacerlo reutilizable, el componente recibe como argumento el item con la información que tiene que rellenar (en nuestro ejemplo, título y una foto) y usamos esta información para completar la creación de los componentes que forman la fila. En la fila 9, creo una propiedad <code class="codecolorer text mac-classic"><span class="text">data</span></code> en el <code class="codecolorer text mac-classic"><span class="text">TableViewRow</span></code> que me permitirá recuperar toda la información del elemento más tarde. Este es el mismo &#8220;data&#8221; que recupero en el eventListener de la tabla.</p>
<p>gist id=3554525 file=PhotosTableViewRow.js]</p>
<h4>PhotoViewer.js</h4>
<p>Este fichero no tiene mucha complejidad. Se tiene en cuenta si la plataforma es iOS o Android, para colocar o no un botón de cerrar (android no lo necesita, ya que dispones de el botón &#8220;volver&#8221;).</p>
<p>Para facilitar la escritura, en el fichero estilos he creado una propiedad iOS que será <code class="codecolorer text mac-classic"><span class="text">true</span></code> si el dispositivo es iPhone o iPad, así resulta más fácil de escribir (y de leer), tan simple como ver el valor de <code class="codecolorer text mac-classic"><span class="text">$$.iOS</span></code>.</p>
<p>Otro punto interesante, podemos agregar nuestros propios métodos a objetos Titanium. A <code class="codecolorer text mac-classic"><span class="text">win</span></code> le añado el método <code class="codecolorer text mac-classic"><span class="text">showImage</span></code>, que es una función que abrirá la ventana en forma modal. (Ojo! No es la mejor manera de hacer esto, pero para el ejemplo queda bien y es suficiente). Así, podemos extender el funcionamiento nativo de los componentes Titanium agregando métodos y propiedades.</p>
<p><strong>Importante</strong> saber que cuando añadamos métodos a objetos Titanium estos no deben nunca empezar con <code class="codecolorer text mac-classic"><span class="text">get</span></code> o <code class="codecolorer text mac-classic"><span class="text">set</span></code>. Es una limitación de la plataforma, fallará en silencio y podemos tirarnos un buen raton sin saber qué pasa o porqué no funciona.</p>
<p>gist id=3554525 file=PhotoViewer.js]</p>
<h4>flickrFeed.js</h4>
<p>Vistos todos los ficheros relativos a la interfaz de usuario, pasamos a ver cómo se gestiona la conexión con el servidor.</p>
<p>El cliente http establece una conexión con un puerto web y hace una petición GET o POST a la url que le indiquemos. HTTPclient permite definir varias funciones callback para gestionar la respuesta del servidor. En este ejemplo uso <code class="codecolorer text mac-classic"><span class="text">onload</span></code> y <code class="codecolorer text mac-classic"><span class="text">onerror</span></code>, pero tambien podemos capturar <code class="codecolorer text mac-classic"><span class="text">ondatastream</span></code> y <code class="codecolorer text mac-classic"><span class="text">onsendstream</span></code> para saber la cantidad de información enviada y recibida.</p>
<p>gist id=3554525 file=flickrFeed.js]</p>
<p>He definido la función <code class="codecolorer text mac-classic"><span class="text">exports.getData</span></code> para que reciba un argumento llamado <code class="codecolorer text mac-classic"><span class="text">callback</span></code>. Titanium llamará la función definida en <code class="codecolorer text mac-classic"><span class="text">onload</span></code> cuando tenga respuesta del servidor. Tras procesar la respuesta, se ejecuta <code class="codecolorer text mac-classic"><span class="text">callback</span></code>, pasándole como argumento la respuesta &#8211; ya procesada &#8211; del servidor. <code class="codecolorer text mac-classic"><span class="text">getData</span></code> no necesita saber qué es o a quién pertenece <code class="codecolorer text mac-classic"><span class="text">callback</span></code>, simplemente la intentará ejecutar suponiendo que se trata de una función y que sabrá como ejecutarse. En el ejemplo, lo que ocurrirá es que se llamará a <code class="codecolorer text mac-classic"><span class="text">callbackTableview</span></code>, que es la función que pasamos como argumento a <code class="codecolorer text mac-classic"><span class="text">Feed.getData</span></code> y si todo va bien, rellenará la tabla con las fotos.</p>
<p><em>He observardo que algunas tags en flickr generan una respuesta json que titanium no puede procesar, si haces pruebas cambiando las palabras en la URL, puede que falle por esto.</em></p>
<h4>Eventos vs. callbacks</h4>
<p>Espero dedicar en algún momento una entrada sólo a la creación y gestión de eventos, pero quiero hacer una pequeña aclaración de porqué es preferible usar callbacks a eventos a nivel de app. Primero, hay que diferenciar entre lo que son eventos de componentes gráficos (como <code class="codecolorer text mac-classic"><span class="text">click</span></code>, <code class="codecolorer text mac-classic"><span class="text">load</span></code>, etc.) y eventos de aplicación. Los eventos de aplicación son los que se gestionan desde <code class="codecolorer text mac-classic"><span class="text">Ti.App.addEventListener()</span></code> y <code class="codecolorer text mac-classic"><span class="text">Ti.App.fireEvent()</span></code>. Lo que explico a continuación afecta a ambos, pero especialmente a los segundos.</p>
<p>Por explicarlo de forma gráfica, una función callback es una conexión directa entre dos objetos. Un objeto llama a un método de otro objeto. No hay intermediarios. Fin de la historia.</p>
<p>Un evento de aplicación es más complejo. Se dispara un evento desde un punto de la aplicación, la aplicación recoge el evento y lo &#8220;reparte&#8221; entre los otros módulos que previamente estarán escuchando. El simple hecho de estar escuchando eventos ya tiene un coste. Como además, el evento es a nivel de app, salta de un módulo al objeto Ti.App y de éste a los que estén escuchando.</p>
<p>En casos en los que sólo queremos comunicar dos objetos es preferible usar callbacks.</p>
<p>Si estamos creando componentes reutilizables, normalmente componentes UI, podemos disparar nuestros propios eventos de componentes (por ejemplo, si nos inventamos un botón que implementa un evento <code class="codecolorer text mac-classic"><span class="text">tripleclick</span></code>)</p>
<p>Y sólo en los casos en que necesitemos llamar la atención de varios objetos no conectados entre sí desde un único punto de la aplicación nos plantearemos usar eventos de aplicación.</p>
<p>&nbsp;</p>
<p>Tienes <a href="https://github.com/jaraen/TitaniumBlogTablesAndCallbacks" target="_blank">los ficheros de este proyecto disponibles para descargar aquí.</a></p>
]]></content:encoded>
			<wfw:commentRss>https://www.criteriastudio.com/titanium-tablas-y-callbacks/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
