I'm looking into ways to save memory in Sencha Touch 2. I see two options, as I'll describe below.
I'd like to get advice on the difference of memory consumption between the two options, and to know if I'm missing anything.
Memory-saving options
Remove and Destroy
Remove unused components from their containers, and destory them. When they're needed again, re-create them.
Advantage:
this approach can be greatly assisted by container ref's 'autoCreate' option and by container config's 'autoDestroy' option.
Disadvantage:
to re-create the view as it was before destruction, you need to make sure every important piece of information you wish to recreate (e.g. scroll-location in list, map-center in map) is kept as state elsewhere.
Remove
Remove unused components from their containers WITHOUT destroying them. When they're needed again, re-attach them to their containers.
Advantages
no need to keep GUI-related information somewhere as state.
the component could be updated even when not appearing in the DOM.
Disadvantages
the component is cleared from the DOM, but the Sencha object is still kept in memory
you'd need to keep detached components somewhere, and make sure to check for - and attach - existing ones before creating new ones
I also posted this on the Sencha forums: http://www.sencha.com/forum/showthread.php?200314-Memory-Management-Options
I got the following, rather general answer:
If you remove the component but do not destroy it, you minimize DOM size but of course you still have that component in device memory. The benefit is since DOM size is down, you have better performance and DOM size is going to have a larger impact than having some components in memory.
Related
My team and I have to make a license plate scanning app as a school project. With that, we have comments and pictures which can be added to cargo. Whenever the user scans a plate they also get the chance to change the checked info in case of a mistake. The problem is that whenever we delete data from the scanned plate it doesn't show on the screen that it has been deleted until we go to another screen. The same goes for the lazy column which we use for inserting new instances of comments and pictures. The data doesn't show on screen until we turn our screen or go back to another screen. private val pictureList = mutableListOf() is what we use for the pictures and for the text we use var countryCode by remember { mutableStateOf(CountryCodeText) }
var licenseNumber by remember { mutableStateOf(LicenseNumberText) }. pictureList is a global variable and the other ones are local variables which use global variables in the mutableStateOf. How can we make sure that the UI updates whenever the data changes? In advance I want to say thanks for the help! (Code is written in Kotlin and jetpack compose)
Just replace the mutableListOf() with a mutableStateListOf(...), and prefer to keep all the state logic confined to a ViewModel. The viewmodel should preferably be only one for the entire app, and the entire app should have only one activity.
The viewmodel should act as a single source of truth for the entire activity's UI state, while also handling all the updates to the UI efficiently.
The #Composables should only be incharge of displaying the state, and sending events to the viewmodel to update the state, for example, an onClick event may be sent up to the viewmodel by a button too trigger a state change in another part of the app.
Take this codelab to learn all about state in Compose (Well, not all, really, but good starter).
Also, changing screens destroys all the #Composables of the current screen, and so when you ce back there, all the #Composables are re-created, and the correct data is fetched. If you wish to trigger "recompositions" upon changing a variable, you must ensure that the concerned variable is a state-holder, i.e., initialized with one of the pre-built state initializers, like mutableStateOf(), or mutableStateMapOf, etc.
We usually have a mutableState*Of format for determining whether a pre-built state initializer is available. The most common ones are covered, obviously, but if not, you'll need to create a new type of initializer yourself, and if that is not something you know how to do, currently, you can just go about checking whether the type of data you wish to store is Immutable. If so, you can just wrap it in a mutableStateOf<DataType>() call, and it will trigger the recompositions. Know that this is not as efficient as pre-built initializers, but definitely gets the job done.
Also, I suggest you take the compose-pathway to get the basics down. It covers everything ranging from creating a simple UI using basic pre-built Layouts to creating a complex animation-driven application using custom Layouts.
So, definitely a lot to take it, but I hope you get there.
Happy composing,
So i have a titanium app, and i just read about single contexts. (Incidentally, somebody here should write a book about programming in titanium... the only one out there doesn't really mention single contexts or any of that new-fangled stuff. Heck, make it an eBook. I'd buy it)
The titanium documentation stresses their use (http://docs.appcelerator.com/titanium/latest/#!/guide/Coding_Strategies-section-29004891_CodingStrategies-Executioncontexts) and then politely forgets how to implement a single context!!
So, question:
Let's say i have the awesomeWidget page - this just shows a button, and when you click on a button a new screen appears.
The aswesomeWidget page is accessed through another page - it is not from the root of the titanium app.
Keeping to single contexts, how do i add the view that the button creates to the current window?
Do I:
keep a global pointer to the current (and only) window?
pass the variable holding the current window down to all the following pages that use it
something else?
First off, Titanium keeps a reference to your current window anyway for you, so this use case is easy. For example:
awesomeWidgetButton.addEventListener('click' function(e) {
var yourView = Ti.UI.createView({...});
Titanium.UI.currentWindow.add(yourView);
});
If you want to dig further, the concept of a single context is closely tied to the use of CommonJS modules and the require keyword. It is very simple to keep a single context, just never open a window with the url component filled out, and liberally use the require() keyword. Other than that, its up to your imagination to keep track of who points to what and vice versa, there are standard patterns and best practices that apply here (MVC, Singletons, just keep it simple) just as in coding in any other language.
I am implementing a view model that is shared by applications on multiple platforms. I am using MvvmCross v3 that has its own MvxEventToCommand class, but I believe the challenge is the same for other frameworks like MVVM Light. As long as the event is used without parameters, the implementation is straightworward, and this is the case for simple interactions like tapping the control.
But when the command needs to handle event arguments things become more complicated. For example, the view model needs to act on certain scroll bar changes (and load more items in the associated list view). Here is the example of XAML:
<cmd:EventToCommand
Command="{Binding ScrollChanged}"
CommandParameter="{Binding EventArgs}" />
(MvvmCross uses MvxEventToCommand, but the principle is the same).
Then in my model I can have the following command handler:
public ICommand ScrollChanged
{
get
{
return new RelayCommand<ScrollChangedEventArgs>(e =>
{
MessageBox.Show("Change!");
});
}
}
(MvxCommand in MvvmCross).
The problem is that ScrollChangedEventArgs is platform specific and this code simply will not compile in a portable class library. This is a general problem with any command that needs not only a push when an event was fired but requires more specific event details. Moving this code in platform-specific part is silly because it more or less kills the concept of portable view models and code-behind-free views. I tried to search for projects that share view models between different platforms, but they all use simple events like "Tap" with no attached event details.
UPDATE 1 I agree with Stuart's remark that view models should only deal with higher level abstractions, so I will rephrase the original concern: how to map results of low-level interactions to a platform-neutral event that triggers a business logic command? Consider the example above: the business logic command is "load more items in a list", i.e. we deal with a list virtualization where a limited number of items from a large collection are loaded initially, and scrolling down to a bottom of a list should cause additional items to be loaded.
WinRT can take care of list virtualization by using observable collections that support ISupportIncrementalLoading interface. The runtime detects this capability and automatically requests extra items from a respective service when the user scrolls down the list. On other platforms this feature should be implemented manually and I can't find any other way than reacting on ScrollViewer ScrollChanged event. I can see then two further options:
Place OnScrollChanged handler in a code-behind file and call the portable view model higher level event (such as "OnItemsRequested");
Avoid code-behind stuff and struggle to wire the ScrollChanged event directly to a view model, then we will need to remap the platform-specific event first.
As long as there is no support for second option, putting event handler in code-behind file is OK as long as it is done for the sole purpose of event mapping. But I would like to investigate what can be done using the second option. MvvmCross has MapCommandParameter class which seems to be able to help, so I wonder if I should exploit that one.
UPDATE 2 I tried MapCommandParameter approach, and it worked allowing me to insert a platform-specific adapter that would map low-level events to view model-specific commands. So the second option worked without any struggle. Stuart also suggested listview-subclassing so there is no need to care about scrolling events. I plan to play with it later.
I agree that viewmodel commands should normally be expressed in terms of viewmodel concepts - so it would be 'strange' to send the viewmodel a command about the scrollbar value changing, but it might be ok to send the viewmodel a command about the user selecting certain list elements to be visible (which she does via scrolling)
One example where I've done this type of thing previously is in list selection.
I originally did this across multiple platforms using a cross-platform eventargs object -
https://github.com/slodge/MvvmCross/blob/vnext/Cirrious/Cirrious.MvvmCross/Commands/MvxSimpleSelectionChangedEventArgs.cs
this was then used on WindowsPhone (for example) via an EventToCommand class like https://github.com/slodge/MvvmCross/blob/vnext/Cirrious/Cirrious.MvvmCross.WindowsPhone/Commands/MvxSelectionChangedEventToCommand.cs
However... I have to admit that this code hasn't been used much... For list selection we have instead mainly used selecteditem binding, and there simply haven't been any apps that have needed more complex parameterized commands (so far) - you might even need to go back to very old v1 mvvmcross code to find any samples that use it.
I am writing an app in which I have two UITextFields...
Starting Text
Destination Text
Now once I place values and hit the search or whatever function I want to call, I Want to reuse these values. The app should record and save these values as cache. And should show them when typing or upon a button click. Is that possible to show them just like Dictionary words show up or Which is more preferable tableView or PickerView? If there is any other please let me know.
Definitely use a UITableView. A UIPicherView is used modally most of the time and not for optional suggestions.
Table view is used in Safari, and a lots of other apps:
As for how to cache the data, you have lots of options. It also depends on how much data you expect.
One easy way would be to simply use NSArray. You can very easily write an NSArray to disk in a plist file and read it back when you need it.
Or you could use Core Data, if you expect lots of data and still want high performance. It will be a lot more difficult though to get used to that API if you've never tried it before. Basically you'll need a simple model with one entity called something like SearchEntry that has a single property text. Then you keep adding new instances to your managed object context and can easily filter the existing values.
I have made like an "Asteroid" copy, that works pretty well! I made it with different modules (enemies, controls and background). Now I have also made like a starting screen, where the player can choose to play the game, view highscores etc.
The problem is that I have no clue how to implement this into a storyboard.. I might have misunderstood the use of modules.
I am starting in a Scene1, which is the intro+buttons to start the game. Next, I want to move to scene2(when player presses start button), and that seems to be no problem, and scene 1 gets purged. But when I die, I want to move to scene1 again. Problem is that some listeners dont get removed, and the game crashes shortly after scene switch.
I guess the main problem is that in my scene2, I have put in require("background"), enemies and controls in my enterscene, which I dont know how to remove when it should be purged.
Ive entered all of the modules and put them in the same group that gets purged on exitscene, but not everything gets removed.
How do you think I would fix this the easiest way? I am very new to Corona and still in a early learning stage.
Display objects, like display.newImageRect()'s and display.newText() that are created in the createScene() function and added to the "group" display group will be automatically removed when the scene is purged.
Any timers, transitions, or audio.plays that have onComplete handlers, as well as network requests and any event handler that attaches to the Runtime must be removed by hand. If you're various object you are creating are doing any of these things, their remove functions should undo these actions so that removing them will clean them up.
I find it best if I'm adding runtime handlers, timers, etc. to do it in enterScene() and make sure I undo them in exitScene(). Then if its something that is done in createScene() it should be cleaned up in destoryScene().
modules are kind deprecated to start.
Second, putting stuff in other files and calling them with "require" is supposed to be used to call libraries, not code that will run. "require" is not a dofile, or a eval, it will run once, and only once (when the first "require" of the file is made).
If you still want to put things in other files, like loading your background, you need to do a "background.lua" file that has a "background.load()" function and a "background.unload()" function, and call them in appropriate places.