Advanced Tasker: Circumventing speed issues with global arrays in menu scene elements
Disclaimer: Advanced Tasker is a new series of Tasker articles that go beyond the beginner’s guide, and that are aimed at those who have full control over everything covered in the guide. In this article series, step by step instructions will not be provided, there won’t be any downloadable files, and questions that belong in the beginner’s guide will not be answered. The aim of these articles is to discuss ideas that can be implemented in many different ways, in many different projects- and that requires the ability to create things from scratch, not by following step by step guides.
In part 7 of the beginner’s guide I mentioned that I already knew of ways to speed up my todo list, and that there might very well be a V3 of the list that was shown off in V2 form in that article. Well, a V3 has been made, so has a V4, and while I haven’t made a V5, I’ve made another “app” that improves on the system the same way that a V5 of the list would. I haven’t talked much about these improvements so far, because V2 was really the last version of the list that could in any way to crowbared into the “beginner” definition. With this new series, however, I can finally talk about what I’ve learned without having to explain each of the several hundred actions in detail.
The menu scene element is one of the most powerful tools in Tasker, assuming you know how to use it. It’s very dynamic, and allows you to create a simple interface for dealing with data in massive quantities. My todo list is just one example, a file browser another, and the before mentioned new “app” (it’s so weirdly specific to my situation that I won’t even bother explaining what it does) a third. Unfortunately, there’s one rather massive issue with the menu element: There’s no way to feed it a local array. Because it’s technically a separate entity from other task, and as such don’t fall within those tasks’ definition of “locale”, it requires a global array to populate it.
Global variables are much slower than local ones, because they have to be updated throughout Tasker when set. Since a global array is a collection of global variables, and an array often contain dozens of entries, the normally hardly noticeable difference is suddenly measured in seconds. Suffice it to say, you don’t want an app that takes tens of seconds to update a list. I tried making a global array based file browser once, and it was stupid slow. Thanks to some help from the community I was able to device a better way, and it’s that method that I’ve now taken much further.
The whole idea is to only work with an array when you’re in a local task, and store the contents of that array as a global variable when moving between tasks (or scene elements). By setting a variable to %array(), you’re creating a single variable that has each item from the array as a comma separated list, thus creating only a single global variable. That variable can then be used in the menu scene element, as that supports comma separated lists. So, instead of feeding the menu an array, you’re feeding it a single variable that contains the contents of an array. The resulting menu looks the same, with each item from the comma separated list (i.e. each array item) listed individually.
Of course, this leaves you with a single variable of data, which isn’t necessarily ideal for other uses. I’ve experimented quite a bit, and found that while it is technically possible to use Variable Search Replace or Variable Split as substitutes for Array Pop and Array Push, it’s far from ideal. The biggest issue I’ve had is with runaway spaces and line shifts, which have long ago climbed to the top of my list of most annoying Tasker issues. Because my todo list writes to text files, which appends a line shift at the end, I ended up with random line shifts all over the place. You can use Variable Search Replace to get rid of those if each item in your list is void of any spaces (like a list of URLs, but that method doesn’t work for things like todo lists, which have spaces that should be there.
Long story short, it’s much easier to work with arrays, so why not just do that? Each time you need to manipulate the contents of the list, simply copy the global variable that contains your list to a local variable, and split it by the comma. Splitting by a comma and setting a variable to %array() are opposites, so you can go back and forth between single variables and beautiful local arrays this way. Then you have a local array that you can use Pop and Push on, use individual variable tools on, run through For loops, and so on. Because the item number in the list will directly correspond to the resulting array number, you can still use the tap and selected variables generated by interacting with the list. Tap the third item on the list, and the contents can be found in %array(%tap_index). At the end of the task, simply put the edited local array back into a single global array, and your list should update as if it was using the array as a source.
The speed difference you’ll be seeing over using a global array is ridiculous, and you’re going to have to come up with a lot less weird fixes by using this method over trying to edit the global variable instead of converting back to a local array. V3 and V4 of my todo list uses the global variable editing system, which means it’s fast, but there’s a scary amount of workarounds for loose line shifts and empty variables in there. The other app I was talking about uses this new hybrid system that switches between local arrays and a global variable, and it’s just so much easier to set up. I have yet to make a V5 of my todo list system since there wouldn’t be any obvious advantages now that the workarounds are already in place, but it would likely cut a good 50 actions off the total for the entire project if I did.