Ver la Versión Completa : [ CONSULTA ] Variables locales o globales en consultas SQL y Elementos Menú en Escenas
Buenas, estoy tratando de optimizar un proyecto que uso para administrar los contactos de mi agenda, para poderlos usar como condicionales en diferentes perfiles y tareas.
Actualmente utilizo variables Globales, y la escena, de forma resumida contiene lo siguiente:
Elemento menú habilitados
- Muestra los contactos habilitados.
- Origen: Array - %Habilitados.
- Clic: Limpia variable %Habilitados(%tap_index) y Array Push %Deshabilitados.
Elemento menú deshabilitados
- Muestra los contactos deshabilitados.
- Origen: Array - %Deshabilitados.
- Clic: Limpia variable %Deshabilitados(%tap_index) y Array Push %Habilitados.
Elementó botón habilitar todos los contactos
- Array clear %Deshabilitados.
- Consulta SQL en DB de contactos y almacena resultado en %Habilitados.
Elementó botón deshabilitar todos los contactos
- Array clear %Habilitados.
- Consulta SQL en DB de contactos y almacena resultado en %Deshabilitados.
Al usar variables Globales, el proyecto funciona de forma correcta, y tengo disponible el los Arrays %Habilitados y %Deshabilitados, conteniendo cada uno de ellos los contactos que me interesen en cada momento.
El problema es que en un solo proyecto tengo tantas variables Globales, como contactos en la Agenda, que en mi caso pueden ser alrededor de 300.
Realmente, no noto que perjudique en nada en el rendimiento del proyecto, pero si que he notado que la consulta SQL a la que me refiero en la descripción anterior, se ejecuta infinitamente más rápido si almaceno el resultado en variables Locales.
Estoy dándole vueltas a ver la manera más efectiva de poder usar variables locales en vez de globales.
Por lo pronto, lo único que se me ha ocurrido, es sustituir las variables globales por locales y añadir una acción después de cada tarea indicada anteriormente, que establezca %Habilitados a %habilitados() , y así almacenar todos los contactos habilitados y deshabilitados en una sola variable Global, y poder utilizar su contenido como condicional.
Como he comentado varias veces, una de mis tareas pendientes es saber gestionar mejor el uso de variables locales, así que recurro aquí para ver si alguien tiene alguna idea mejor. Un Saludo.
WillyWeb
18/11/17, 12:01:19
El problema es que en un solo proyecto tengo tantas variables Globales, como contactos en la Agenda, que en mi caso pueden ser alrededor de 300.
Veo que esas variables globales son los elementos de un array y que ya has valorado guardar todo su contenido en una única variable.
... si que he notado que la consulta SQL a la que me refiero en la descripción anterior, se ejecuta infinitamente más rápido si almaceno el resultado en variables Locales.
Un efecto secundario de usar muchas variables globales es que se resiente la velocidad de ejecución, sobre todo en arrays y bucles.
... lo único que se me ha ocurrido es sustituir las variables globales por locales y añadir una acción después de cada tarea ... que establezca %Habilitados a %habilitados() y así almacenar todos los contactos habilitados y deshabilitados en una sola variable Global ...
Yo también he usado esa técnica. Es fácil de implementar y funciona razonablemente bien.
Yo también he usado esa técnica. Es fácil de implementar y funciona razonablemente bien.
Si tu usas o has usado esta técnica me quedo mucho más tranquilo.
Desde que empecé con Tasker, entendí que las variables locales, únicamente tiene valor el tiempo que dura la ejecución de la tarea en la que aparecen, por eso las descartaba siempre a la hora de usarlas en el elemento menú de una escena.
Como he comentado, en una escena tengo dos elemento menú, que se llenan con los arrays %habilitados y %deshabilitados, y he podido usar la acción Array Push, para añadir elementos a cada uno de los Arrays, por lo que si no me equivoco, parece que el valor de las variables locales, sobreviven mientras la escena se encuentre abierta, independientemente de que se figuren o no, en una misma tarea.
WillyWeb
19/11/17, 11:40:59
... si no me equivoco, parece que el valor de las variables locales, sobreviven mientras la escena se encuentre abierta ...
Así es, las variables locales se "comparten" entre las escenas y las tareas desde las que se abre.
danko9696
19/11/17, 15:41:28
Desde que empecé con Tasker, entendí que las variables locales, únicamente tiene valor el tiempo que dura la ejecución de la tarea en la que aparecen, por eso las descartaba siempre a la hora de usarlas en el elemento menú de una escena.
En cada tarea dentro de la cual llames a escenas, lo primero de todo pasa las globales a locales y al final de todo de locales a globales. No hay necesidad de usar globales entre medias ni problema en usarlas con menus ni otros elementos de escena.
También puedes tener las globales fuera de la tarea, en lugar de como array como una cadena, en plan AAAA,BBBB,CCCC (o si no puedes tener comas, usando otro símbolo menos frecuente como AAAA~BBBB~CCCC....).
Esa cadena, además te puede servir para algunas comparaciones que van van a ser más rápidas que de forma global. Por ejemplo, si quieres saber si el contacto BBBBB está en la lista de habilitados puedes recorrer un array o puedes usar la comparación de si está contenido en esa cadena AAAAA,BBBBB,CCCCC..., bastante más rápido que recorrer un array, aunque dependiendo de exactamente lo que quieras hacer puede que no sirva.
Como he comentado, en una escena tengo dos elemento menú, que se llenan con los arrays %habilitados y %deshabilitados, y he podido usar la acción Array Push, para añadir elementos a cada uno de los Arrays, por lo que si no me equivoco, parece que el valor de las variables locales, sobreviven mientras la escena se encuentre abierta, independientemente de que se figuren o no, en una misma tarea.
Siguiendo con el punto anterior, no siempre va a ser posible, pero otra forma de añadir elementos es, si siempre los añades al final, concatenarlos a una cadena simple. Si quieres añadir un contacto al final %habilitados, en lugar de push puedes simplemente asignar %habilitados~%nuevo_contacto a %habilitados. Luego, justo antes de que vayas a usarlo en el elemento menu haces un split para convertir %habilitados en un array. Esto tiene la ventaja, además, de que resulta más fácil de depurar o como algo a mostrar durante el uso normal, ya que puedes mostrar el contenido del "array-cadena" con un sencillo alert de %habilitados.
También puedes tener las globales fuera de la tarea, en lugar de como array como una cadena, en plan AAAA,BBBB,CCCC
Con esto te refieres, a guardar el contenido en una única variable no? Si es así, es la opción que estoy utilizando y me esta funcionando bien. Relleno el elemento menú con el Array local %habilitados, y luego establezco %Habilitados a %habilitados()
si quieres saber si el contacto BBBBB está en la lista de habilitados puedes recorrer un array o puedes usar la comparación de si está contenido en esa cadena AAAAA,BBBBB,CCCCC
Eso lo estoy haciendo así; IF %Habilitados ~ *BBBBB* , no se si hay alguna forma más eficaz.
bastante más rápido que recorrer un array
Eso es justo lo que estoy buscando, velocidad, optimización... para este y para futuros proyectos.
Si quieres añadir un contacto al final %habilitados, en lugar de push puedes simplemente asignar %habilitados~%nuevo_contacto a %habilitados
En este caso no puedo hacerlo así, porque las modificaciones de los arrays %habilitados y %deshabilitados, los muestro en tiempo real, en dos elementos menú.
danko9696
20/11/17, 01:33:08
Con esto te refieres, a guardar el contenido en una única variable no? Si es así, es la opción que estoy utilizando y me esta funcionando bien. Relleno el elemento menú con el Array local %habilitados, y luego establezco %Habilitados a %habilitados()
Sí, es que no me quedaba claro si %Habilitados lo tenías como array o como cadena simple.
En este caso no puedo hacerlo así, porque las modificaciones de los arrays %habilitados y %deshabilitados, los muestro en tiempo real, en dos elementos menú.
Me refería a añadir elementos y mostrarlos a efectos de depuración, no de forma definitiva. O sea, operar con una cadena para luego convertirla en array usando un sencillo split justo antes de enviarla al menu. Pero antes de esto (de convertirla en array) lo que te decía es que puede resultar útil para depurar la capacidad de poder mostrar resultados intermedios usando un alert de la cadena, el cual, una vez comprobado que funciona todo bien, puedes eliminar.
Por lo menos en mi caso, si usase push, en algunas tareas la depuración habría sido muy muy complicada. Mientras que de esta manera puedes meter alert en diversos puntos para ver la evolución dentro del bucle (por ejemplo, ver el contenido de la cadena-array en la vuelta 10 y 50 del bucle). Así, puedes meter un alert de %habilitados (no array) si %cont_bucle = 10 o %cont_bucle = 50, y eliminar/deshabilitar dicho alert una vez terminado y funcionando todo bien. En tu caso seguramente no haga falta pero yo lo tendría en cuenta para tareas más complicadas, por ejemplo te facilita también usar un bucle de varios niveles, aunque si es el caso posiblemente podrías usar sqlite si son bastantes datos.
Igual no es la mejor forma pero yo nunca uso push. Me resulta más comodo trabajar siempre con cadenas y convertirlas en arrays solo cuando es necesario.
Me refería a añadir elementos y mostrarlos a efectos de depuración, no de forma definitiva. O sea, operar con una cadena para luego convertirla en array usando un sencillo split justo antes de enviarla al menu
En mi caso obtengo el contenido del array %habilitados, con una consulta SQL a la DB de los contactos, a continuación uso la acción de Procesar Array "Eliminar duplicados" y "Comprimir (Squash)", y finalmente establezco %Habilitados a %habilitados().
No utilizo bucles, y en este caso no tengo necesidad de comprobar previamente el resultado antes de mostrarlo en el elemento menú, además desde que estoy usando el array local, la tarea se ejecuta en 100 milisegundos aproximadamente. Antes tardaba entre 2 y 3 segundos...
No obstante tomaré nota, por si en algún momento tengo que trabajar con arrays con más contenido. Gracias de nuevo por los consejos. Un saludo.
danko9696
20/11/17, 20:45:13
En mi caso obtengo el contenido del array %habilitados, con una consulta SQL a la DB de los contactos, a continuación uso la acción de Procesar Array "Eliminar duplicados" y "Comprimir (Squash)", y finalmente establezco %Habilitados a %habilitados().
No sé bien por qué usas la acción de eliminar duplicados y huecos cuando la consulta sqlite ya debería dejarlo listo a este respecto.
Lo de comprimir (squash) lo uso para cuando tocó un contacto, pasa de %habilitados a %deshabilitados, y no quiero que se quede un hueco en el elemento menú. Lo de eliminar duplicados si que es cierto que sobra, en su momento lo pondría por algún motivo y ahí se ha quedado...
Tengo una nueva consulta en relación a la sustitución de variables globales por locales en el proyecto descrito.
Es difícil de explicar, sin ver cómo funciona la escena, pero lo voy a intentar.
Cómo he comentado, he modificado los arrays globales por locales y funciona perfectamente, pero en la misma escena tengo una acción de consultar variable que utilizo para hacer un INSERT en la DB SQL que tengo alojada en el servidor.
El problema es que, al usar la acción de consultar variable, se muestra la escena correspondiente de Tasker de "consultar variable" y eso hace que el resultado del array local, no se muestren en el elemento menú de la escena.
El caso es que si muestro el array() con una acción flash, compruebo que los elementos tienen asignado el valor correcto, pero para que se muestre en el elemento menú, me estoy viendo obligado a tener que interactuar nuevamente con la escena, usando cualquiera de las acciones de "procesar array"
Esto no ocurría al utilizar los arrays globales.
Por lo pronto no encuentro ninguna otra solución.
WillyWeb
26/11/17, 09:27:13
El problema es que, al usar la acción de consultar variable, se muestra la escena correspondiente de Tasker de "consultar variable" y eso hace que el resultado del array local, no se muestren en el elemento menú de la escena.
La escena estándar que usa Tasker para consultar variable no tiene un elemento menú. :rolleyes:
¿Estás usando una escena personalizada?
Uso una escena personalizada de consultar variables, pero el elemento menú, lo tengo en la escena principal.
Voy a adjuntar un vídeo para que se entienda mejor el problema.
https://youtu.be/YzCNY2Qdj4o
Al pulsar sobre el icono de añadir que tengo en la escena principal, básicamente lo que hago es un INSERT en la DB, luego un SELECT para mostrar la DB, y luego las acciones correspondientes de JS que me facilitaste tu.
Hasta hay todo funciona bien, y como he comentado, si muestro el resultado del array en una acción flash compruebo que está correcto, pero me veo obligado a interactuar nuevamente con la escena principal, para que se muestre el resultado en el menú.
En el elemento texto "CONTINUAR" únicamente añado una acción de procesar array y ocultar ese elemento, y ya se muestra.
Cuando usaba variables globales, no me hacía falta interactuar nuevamente con la escena.
WillyWeb
26/11/17, 12:10:13
En principio las variables locales se comparten entre la tarea en la que se crean y las escenas que se lancen desde ella, y tengo verificado que eso funciona. No conozco la estructura de tu proyecto, pero parece que tienes una tarea principal desde la que lanzas escenas y subtareas que meten mano a esas variables locales. No tengo verificado que las variables locales se compartan igual entre tarea-subtarea que entre tarea-escena.
Alguien que haga la prueba ¿...? :silbando:
De todas formas, si crees algo no está funcionando como debería puede tratarse de fallo de Tasker, que no sería el primero. Yo ya he reportado tres en el foro de soporte.
¿Has preguntado a Pent sobre ese tema? :rolleyes:
Es posible que como tú dices, sea un fallo de Tasker, porque como he comentado, si añado una acción flash array(), al final de la tarea asignada al botón de añadir, muestra el contenido de forma correcta, por lo que doy por hecho que el array local está definido.
Así que supongo que tendré que comunicarlo en el foro de Tasker, o simplemente mantener lo de "CONTINUAR" para que se muestre en el elemento menú de la escena.
Por cierto, si quisieras ver cuál ha sido el resultado final del proyecto, ya que has sido el que me has ido guiando en todo lo relacionado con la comunicación con la DB, te puedo pasar el XML, o bueno, a cualquiera que esté interesado.
WillyWeb
26/11/17, 12:39:24
... si añado una acción flash array(), al final de la tarea asignada al botón de añadir, muestra el contenido de forma correcta ...
¿Y si haces ese flash una vez terminada esa subtarea, de regreso a la tarea principal?
Por cierto, si quisieras ver cuál ha sido el resultado final del proyecto ... te puedo pasar el XML ...
No me importaría, pero valora las consecuencias de hacer público un proyecto pensado para uso privado.
¿Y si haces ese flash una vez terminada esa subtarea, de regreso a la tarea principal?
No me importaría, pero valora las consecuencias de hacer público un proyecto pensado para uso privado.Cuando he añadido la tarea flash, ha sido al final de la tarea asignada al botón añadir. Creo que es eso a lo que te refieres.
Lo de compartir el proyecto, no pensaba en hacerlo aquí públicamente. No tiene ningún dato personal que me pueda perjudicar creo.
No obstante, como puede manipular la DB que estamos usando para la liga que estamos jugando, no quiero que pueda tener acceso cualquiera y que hagan modificaciones indeseadas.
Pero aquí ya más o menos nos vamos conociendo, y no tendría problemas en compartir proyectos con varios de los que participais en este foro.
Enviado desde mi MI 5s mediante Tapatalk
danko9696
26/11/17, 22:46:52
Cómo he comentado, he modificado los arrays globales por locales y funciona perfectamente, pero en la misma escena tengo una acción de consultar variable que utilizo para hacer un INSERT en la DB SQL que tengo alojada en el servidor.
El problema es que, al usar la acción de consultar variable, se muestra la escena correspondiente de Tasker de "consultar variable" y eso hace que el resultado del array local, no se muestren en el elemento menú de la escena.
El caso es que si muestro el array() con una acción flash, compruebo que los elementos tienen asignado el valor correcto, pero para que se muestre en el elemento menú, me estoy viendo obligado a tener que interactuar nuevamente con la escena, usando cualquiera de las acciones de "procesar array"
No se si se trata del mismo problema exactamente pero me pasó algo parecido trabajando con varios elementos menu en escenas usando javascript. Después de definidos los arrays desde JS la escena cargaba correctamente pero al actualizar dichos menus después de seleccionar elementos y cosas así, modificar el array desde JS no se reflejaba en pantalla, así que me vi obligado a realizar una asignación de variable nativa de tasker, después de lo cual ya si lo hizo correctamente.
El problema lo asocié a un problema de visibilidad debido a usar JS, no pensé que sería por ser un array local pero puede que sea por esto último, dado tu caso. Pero vamos, sabiendolo no supone mucho problema, después de solucionarlo hice varias escenas más ya teniendo en cuenta eso y cero problemas. O sea, desde la tarea madre toda la manipulación de arrays en JS pero desde dentro de la escena cuando se modifica un array también en JS pero no todo, con alguna alguna operación JOIN/SPLIT/del estilo. Parece que necesario para que se propaguen los cambios.
En mi caso, también obtengo el array con JS, y como te pasa a ti, no se refleja en el elemento menú de la escena.
Pero como he comentado, si al final de esa tarea añado una acción flash array(), si que se muestra el resultado de forma correcta.
Solo consigo que se muestre en el elemento menú de la escena, si vuelvo a interactuar con la escena. Como se puede ver en el vídeo, he añadido un elemento texto CONTINUAR con una acción procesar variable - eliminar duplicados, u ordenar etc, cualquiera vale, y entonces si que se muestra en el elemento menú.
He podido comprobar que el origen del error es la acción consultar variable. Como ya sabemos, esa acción contiene una escena, y al mostrarse esa escena causa algún tipo de conflicto que hace que luego la escena principal, en la cual está el elemento menú, no se muestre con los valores de las variables/arrays actualizados.
así que me vi obligado a realizar una asignación de variable nativa de tasker, después de lo cual ya si lo hizo correctamente
Con esto entiendo que en tu caso no necesitas interactuar nuevamente con la escena? me puedes decir que acción utilizas exactamente?
Un saludo.
danko9696
27/11/17, 16:09:54
En mi caso, también obtengo el array con JS, y como te pasa a ti, no se refleja en el elemento menú de la escena.
Por si acaso no hablamos de lo mismo. Sí que se refleja en la escena cuando se trata del array local definido en un JS de la tarea que la llama pero no cuando lo hago desde desde dentro de la propia escena.
Con esto entiendo que en tu caso no necesitas interactuar nuevamente con la escena? me puedes decir que acción utilizas exactamente?
Al seleccionar un elemento de un menu modifico otro realizando una consulta sqlite. Lo único que hice fue, en lugar de hacer el SPLIT dentro del JS, hacerlo fuera.
Aparte, tengo otra acción de Tasker posterior con la que sí interacciono con la escena pero ya estaba antes (cuando no funcionaba el tema del menu), y es para modificar el texto de un label que debo hacer de todos modos.
vBulletin® v3.8.1, Copyright ©2000-2026, Jelsoft Enterprises Ltd.