App performance re: preventing component actions when not in view

Hello all!

We have an application that has many views, panels with sub-panels, etc. and each needs to perform actions (calls to remote services for example) when in view, but not when they are hidden or not in view.

Right now, we check to see if the panel index is 0 and if so we let the panel perform its necessary duties; however, there are times that the panel in question is not in view, or the user has clicked on another tab, so it and/or its owner is still at index 0 and therefore the condition we are using is still satisfied and thus the hidden panel is still going about its business and diminishing performance.

Likewise, we would like to prevent the component(s) from performing unnecessary work when the browser is minimized.

This seems like it would be pretty common hurdle and before we re-invent the wheel or burn time on this, we are hoping that the Enyo community can provide insights/solutions that we could implement. : )

Any help is greatly appreciated.

Thanks in advance, folks!

-Kramerica

BTW - Enyo so far is quite a great framework, we are enjoying it.

Comments

  • catching app-level events about going into the background would be a good thing to add to enyo.Signals. There's already hooks for PhoneGap's top-level pause/resume events, but we don't have hooks right now for some of the new standard events for this kind of thing.

    It would be really useful for panel arrangers to be able to tell the enyo.Panel object if a panel was visible or not. This could allow for better optimization. There's some work here, as arrangers call the getPanels method instead of accessing the panel children directly.
  • As far as I'm aware, a technique like what I use in GVoice/SynerGV and XO should help out some here - although both of those are still Enyo 1.0, the technique should apply directly to Panels, even though I'm still using their predecessor, Views. So, substitute Panels for Pane and Panel for View here :)

    There's an event called when each Pane changes View. In the top-level Pane, I setup that event to call a function that will notify both the incoming and outgoing View that it has gone into or out of view. All of my Views contain that function, and the top-level views will chain it down to any lower level Views. For the most part, those views usually all ignore it, but if they have something special they need to do, they can. I use it on nearly every view in XO to adjust the components that are visible in the toolbars.

    This could probably also be extended to include some additional things, like checking for hide/show or what not. It'd probably be even easier to do in Enyo 2, with the event waterfalling. Of course, when I wrote it I didn't know anything about Enyo event handling, so it was all done with regular js functions.
  • edited August 2012
    I current use show() and hide() to achieve this for a single visible panel arrangement.

    I added the following to my enyo.Panels component as onTransitionStart and onTransitionFinish handlers:
    contentPaneSwitch: function(inSender, inEvent) {
    	if (inEvent.toIndex !== inEvent.fromIndex) 
    		inSender.getControls()[inEvent.toIndex].show();
    },
    
    contentPaneSwitched: function(inSender, inEvent) {
    	if (inEvent.toIndex !== inSender.lastPane) {
    		var pane = inSender.getControls()[inSender.lastPane];
    		if (pane) pane.hide(); // Check first since lastPane may not be defined yet
    		inSender.lastPane = inEvent.toIndex;
    	}
    }
    For each panel that then needs special handling I've extended a kind that looks like:
    enyo.kind({
    	name: 'layout.Panel',
    	kind: 'enyo.Control',
    
    	rendered: function() {
    		this.inherited(arguments);
    		if (this.getShowing()) this.shown();
    	},
    
    	setShowing: function(showing) {
    		this.inherited(arguments);
    		if (showing) this.shown();
    		else this.hidden();
    	},
    
    	shown(): function() { /* Override to handle onShow() actions. */ },
    	hidden(): function() { /* Override to handle onHide() actions. */ }
    });
    Simply set up each panel with showing: false, except for the one that's initially active.

    Apologies for any typos, I've had to refactor it a bit to get rid of all my extra rubbish =)

    Anyway, this works great for simple arrangers such CardArranger or LeftRightArranger with a margin of 0, but any kind that can have more than one pane open at once gets a bit complicated.

    It might be nice to see something similar in the arrangers themselves, using show() and hide() to deal with panels, rather than the current method that seems to use opacity. Especially since arrangers can better decide what is and is not visible.

    Then an enyo.Panel or similar with the same kind of setShowing() change could make the whole thing a bit easier?
  • Oh, I messed up in my simplification and cut out a fairly important bit, here's (hopefully) the full layout.Panel you would need:
    enyo.kind({
    	name: 'layout.Panel',
    	kind: 'enyo.Control',
    
    	beenShown: false,
    
    	rendered: function() {
    		this.inherited(arguments);
    		if (this.getShowing()) this.processShown();
    	},
    
    	processShown: function() {
    		if (!this.beenShown) {
    			this.beenShown = true;
    			this.render();
    		}
    		this.shown();
    	}
    
    	setShowing: function(showing) {
    		this.inherited(arguments);
    		if (showing) this.processShown();
    		else this.hidden();
    	},
    
    	shown(): function() { /* Override to handle onShow() actions. */ },
    	hidden(): function() { /* Override to handle onHide() actions. */ }
    });
    The extra processShown() step is for components that start off hidden, as the call to this.render() forces certain elements (I'm looking at you enyo.List) to update their size to reflect the now visible container, otherwise they get stuck with a height of zero until the window, or a container, is resized.
  • On, the "Panels should show/hide based on visibility" front, there is already a bug on that:

    https://enyojs.atlassian.net/browse/ENYO-578

    I think adding "subpanel appeared" and "subpanel disappeared" events might be good for performance. I'll probably take a look at that while I'm fixing ENYO-578. We want something that works equally well for Arrangers that only display the active panel as for Arrangers that show multiple panels at once, I think.
Sign In or Register to comment.