How to clean up "old" views using sap.m.routing.Router - sapui5

With routing/routes defined in the manifest.json and using Router.navTo() to change the hash and the content of the target App control, I noticed that the "old" views and controllers are still hanging around and listening to events (e.g. performing binding updates for controls that are no longer visible on the stage).
I (wrongly) assumed that the router would clean these views/controls up for me - what is the recommended way doing so?

You are correct. Before calling oRouter.navTo(...) you can call unbind. To give you an example you could check here. There you can find the following line of code inside the onNavBack handler:
this.getView().unbindElement();
unbindElement() is called because previously bindElement(...) was called in the same controller. So just make sure to use bind/unbind combination before oRouter.navTo()...

Related

How to write a method or function to restart the app

I have a game app that, once completed, gives the option to restart. Instead of restarting each method, variable, class, etc separately, I was hoping I could just restart the whole app with the click of a button. Is there a method in swift/xcode to do this?
Thanks!
No, there's not. Best way is to set up an architecture where it's easy to reset everything because all of your state is stored in one place.
For example, inside your AppDelegate/SceneDelegate (whichever architecture you're using), you could have a GameState object that controls all aspects of the game, either by directly holding all of the properties or at least being the common ancestor of everything. Then, when it's time to reset, just create a new instance of GameState().

Does calling removeFromSuperview() on lazy created view instantiate it?

In one of my view controllers, I have a lot of possible subviews that can be created based on the status of the data received. I am trying to make them class variables so they can be accessible throughout the file and am using lazy so that I don't create views I don't need. However, I need to make sure the views that could be displayed get removed if the status changes and would want to call .removeFromSuperview(). But I know that lazy variables get initialized the first time they get referenced and that would defeat the purpose of trying to save memory.
Yes, if you referenced the lazy variable in order to call removeFromSuperview, it would first create the view and then call removeFromSuperview on it. You should likely design another way, without lazy. I would recommend starting with the simplest approach (such as Optional properties, checking if it's nil, and creating it if necessary), and then extracting duplicated code. lazy solves one very specific problem in a very limited way. If you don't need precisely what it offers, you generally will need to build something custom

Views need to be explicit from FuelPHP 1.7?

With no view specificied in FuelPHP 1.6, the default was to load the view located in /views/controller/action but I'm trying FuelPHP 1.7 now and when I don't explicitly forge a view I just get a white output screen. (I checked that is isn't breaking by echoing)
Is this expected behavior? Do views now need to be explicitly called every time?
FuelPHP has never had any code in the default controller classes that loads views automatically based on the controller and action. It sounds like this is custom behaviour that has been added to your application by either yourself or another developer on your project.
You should check what is in the before and after methods of your parent controller as it seems that a minor change in 1.7 has broken your application's logic.
If you get a white output screen, it's actually a normal behavior. You have to forge a view on the methods of your controller.

VM role in MVVM - should it handle everything and why?

Where exactly is the limit to adopt VM so it can suite better a particular View? Example:
There should be a command in UI (ex button) that should allow adding new item. Additional requirement can be that new item should be selected, ensured that its visible on control (lets say TreeView control), and to begin edit on the newly added item (in order to change predefined value that was set in VM). Lets assume that control doesn't have automatic mechanism to achieve this, so we need to do it manually. So the execution flow looks like this:
invoke add command on VM - done is View's xaml.
set SelectedItem to new item (usually we bind control's SelectedItem property to VM's CurrentItem property, and then just assign new item to CurrentItem.
ensure that new item is visible on control - this must be done in View's code behind.
Start editing - this must be done in View's code behind.
Now, since everywhere on net there are articles on using messages for almost everything, a question:
What do I break if I do it in the simple old fashion way? I use Click event instead of Command binding on adding new item, and in the method I do this:
// in View's Click event handler
ViewModel.AddCommand.Execute(null);
EnsureVisibleSelectedItem();
BeginEdit();
.. clean and clear! And what do I gain if I do it using messages:
// in ViewModel's AddCommand
AddNewItem();
SetCurrentItem();
SendMessageToEnsureVisibleSelectedItem();
SendMessageToBeginEditSelectedItem();
... where View has registered to receive these two messages.
Any light on this is greatly appreciated. To my opinion, UI can change, and VM should be able to adopt new UI without making changes to itself, so I dont quite understand current MVVM policy that is preached on internet.
I would say "make it simple".
What's really important in MVVM is:
what doesn't depend on the view should go in the ViewModel (your ViewModel must not be aware of the view in any way - not just by object reference)
everything else in the View and its code-behind.
Yes, in its code-behind. There's nothing wrong in writing code-behind if it is code that is related to the view, not logic. For instance, drag & drop management should be written in the code-behind.
To answer your question, you do not break anything in writing:
// in View's Click event handler
ViewModel.AddCommand.Execute(null);
EnsureVisibleSelectedItem();
BeginEdit();
Everything that is not related to the view is in the ViewModel, everything else in the View/code-behind. That's just fine.
No if I look at your second example:
// in ViewModel's AddCommand
AddNewItem();
SetCurrentItem();
SendMessageToEnsureVisibleSelectedItem();
SendMessageToBeginEditSelectedItem();
AddNewItem is OK (not related to the view), SetCurrentItem is OK (not related to the view), but what about SendMessageToEnsureVisibleSelectedItem and SendMessageToBeginEditSelectedItem?
EnsureVisible is typically useful for a treeview, but what if your view wasn't built with a treeview? What if the control would automatically make the new selected item visible? Of course you could ignore the message, but you would have written some useless code in ViewModel because you thought your view would need it for UI display.
You have typically written here some code in the ViewModel that is aware of how the View should be working. Yes, you have reduced the number of lines in the code-behind, but you definitely have broken the pattern.
Your "old fashion way" is actually a good way for your needs. Your ViewModel is not aware of the view, that's what's important.

Order of evaluation with relative layouts, best practices and parsing of relative-layout

I read this
"
It used to be that Android would use a single pass to process
RelativeLayout-defined rules. That meant you could not reference a widget
(e.g., via android:layout_above) until it had been declared in the XML. This
made defining some layouts a bit complicated. Starting in Android 1.6,
Android uses two passes to process the rules, so you can now safely have
forward references to as-yet-undefined widgets.
"
I do not know what is the problem maybe is eclipse problem, but even I use 2.3 I still have problems when I reference some view that is not declared jet so for me it seems like android doesn't uses two passes to process the rules for relative layout.
note: I always use #+id/widget_name when I declare the widget and #id/widget_name when I reference that widget from other widget. I have noticed that I can use #+id/widget_name even when I just want to reference that widget. I guess that is wrong but why sometimes is works without any complaints ? In my opinion one widget should be allowed to be declared only ones...
My questions is is really android uses two passes ? and I need some guidelines (best practices) for working with relative layouts
I am little confused about how this relative layout parings are made, so any explanations are welcomed
Thanks
#+id/name creates a new id, if it doesn't already exist. #id/name references an existing id, and will never create one.
I'm not sure if you can use #id/name before #+id/name in the same file. If not, I can think of two workarounds:
Always use #+id/name.
Define all id's in the ids.xml file, and always use #id/name.
This is general information on how Android draw views.
I think that Android passes twice through all the view, but it doesn't pass through each single view once. So if you have a reference from one xml to another it will always work fine, but if you have references inside a single xml you must be carefull to order the elements in the xml correctly. For example, I have view1 and view2 in my RelativeLayout. If I want to refer to view2 from view1 I must declare view2 before view1.