[ALOY-834] Android only: Alloy generates addeventlistener call before createTabGroup call causing crash on Android when <Menu> is in XML...
| GitHub Issue | n/a | 
|---|---|
| Type | Bug | 
| Priority | Critical | 
| Status | Closed | 
| Resolution | Fixed | 
| Resolution Date | 2013-09-24T18:45:59.000+0000 | 
| Affected Version/s | n/a | 
| Fix Version/s | Alloy 1.3.0, 2013 Sprint 20 | 
| Components | Runtime, XML | 
| Labels | alloy, android, crash, menu, qe-testadded | 
| Reporter | Henry David Spells III | 
| Assignee | Tony Lukasavage | 
| Created | 2013-09-23T02:50:41.000+0000 | 
| Updated | 2013-10-14T20:44:26.000+0000 | 
Description
	The alloy compiler is generating an addEventListener call on a tabGroup before generating a necessary createTabGroup call. The addEventListener is generated to create the Android menus. I'm pretty sure these were calls were generated in the correct order in Alloy 1.2.0 and possibly 1.2.1.
line 48 of ScheduleGroup.js says
    $.__views.ScheduleGroup.addEventListener("open", __alloyId6);
    $.__views.ScheduleGroup = Ti.UI.createTabGroup({
        tabs: __alloyId7,
        id: "ScheduleGroup",
        activeTabIconTint: "yellow",
        tabsBackgroundSelectedColor: "yellow"
    });
<Alloy>
	<TabGroup id="ScheduleGroup" onOpen="doOnOpen" onFocus="doOnFocus" activeTabIconTint="yellow" tabsBackgroundSelectedColor="yellow">
		<Menu id="menu" platform="android">
			<MenuItem id="refreshMenuItem" title="Refresh" onClick="doRefresh" showAsAction="Ti.Android.SHOW_AS_ACTION_IF_ROOM" itemId="1" />
			<MenuItem id="settingsMenuItem" title="Settings" onClick="doSettingsMenuItem" showAsAction="Ti.Android.SHOW_AS_ACTION_IF_ROOM" itemId="0" />
		</Menu>
		<Require src="scheduleTab" />
	</TabGroup>
</Alloy>
function Controller() {
    function __alloyId6() {
        $.__views.ScheduleGroup.removeEventListener("open", __alloyId6);
        if ($.__views.ScheduleGroup.activity) $.__views.ScheduleGroup.activity.onCreateOptionsMenu = function(e) {
            var __alloyId4 = {
                id: "refreshMenuItem",
                title: "Refresh",
                showAsAction: Ti.Android.SHOW_AS_ACTION_IF_ROOM,
                itemId: "1"
            };
            $.__views.refreshMenuItem = e.menu.add(_.pick(__alloyId4, Alloy.Android.menuItemCreateArgs));
            $.__views.refreshMenuItem.applyProperties(_.omit(__alloyId4, Alloy.Android.menuItemCreateArgs));
            doRefresh ? $.__views.refreshMenuItem.addEventListener("click", doRefresh) : __defers["$.__views.refreshMenuItem!click!doRefresh"] = true;
            var __alloyId5 = {
                id: "settingsMenuItem",
                title: "Settings",
                showAsAction: Ti.Android.SHOW_AS_ACTION_IF_ROOM,
                itemId: "0"
            };
            $.__views.settingsMenuItem = e.menu.add(_.pick(__alloyId5, Alloy.Android.menuItemCreateArgs));
            $.__views.settingsMenuItem.applyProperties(_.omit(__alloyId5, Alloy.Android.menuItemCreateArgs));
            doSettingsMenuItem ? $.__views.settingsMenuItem.addEventListener("click", doSettingsMenuItem) : __defers["$.__views.settingsMenuItem!click!doSettingsMenuItem"] = true;
        }; else {
            Ti.API.warn("You attempted to attach an Android Menu to a lightweight Window");
            Ti.API.warn("or other UI component which does not have an Android activity.");
            Ti.API.warn("Android Menus can only be opened on TabGroups and heavyweight Windows.");
        }
    }
    function doSettingsMenuItem() {
        showHideTabGroup(tabGroup, true);
        openSettingsInContainer(tabGroup.activeTab);
    }
    function doOnFocus() {}
    function doOnOpen() {
        setupAndroidMenuIcons(tabGroup);
    }
    function doRefresh(e) {
        globalEvtMgr.fireevent("refresh", "", e);
    }
    require("alloy/controllers/BaseController").apply(this, Array.prototype.slice.call(arguments));
    this.__controllerPath = "ScheduleGroup";
    arguments[0] ? arguments[0]["__parentSymbol"] : null;
    arguments[0] ? arguments[0]["$model"] : null;
    arguments[0] ? arguments[0]["__itemTemplate"] : null;
    var $ = this;
    var exports = {};
    var __defers = {};
    $.__views.ScheduleGroup.addEventListener("open", __alloyId6);
    var __alloyId7 = [];
    $.__views.__alloyId8 = Alloy.createController("scheduleTab", {
        id: "__alloyId8"
    });
    __alloyId7.push($.__views.__alloyId8.getViewEx({
        recurse: true
    }));
    $.__views.ScheduleGroup = Ti.UI.createTabGroup({
        tabs: __alloyId7,
        id: "ScheduleGroup",
        activeTabIconTint: "yellow",
        tabsBackgroundSelectedColor: "yellow"
    });
    $.__views.ScheduleGroup && $.addTopLevelView($.__views.ScheduleGroup);
    doOnOpen ? $.__views.ScheduleGroup.addEventListener("open", doOnOpen) : __defers["$.__views.ScheduleGroup!open!doOnOpen"] = true;
    doOnFocus ? $.__views.ScheduleGroup.addEventListener("focus", doOnFocus) : __defers["$.__views.ScheduleGroup!focus!doOnFocus"] = true;
    exports.destroy = function() {};
    _.extend($, $.__views);
    var tabGroup = $.ScheduleGroup;
    Alloy.Globals.tabGroup = tabGroup;
    Alloy.Globals.tabBarVisible = true;
    __defers["$.__views.refreshMenuItem!click!doRefresh"] && $.__views.refreshMenuItem.addEventListener("click", doRefresh);
    __defers["$.__views.settingsMenuItem!click!doSettingsMenuItem"] && $.__views.settingsMenuItem.addEventListener("click", doSettingsMenuItem);
    __defers["$.__views.ScheduleGroup!open!doOnOpen"] && $.__views.ScheduleGroup.addEventListener("open", doOnOpen);
    __defers["$.__views.ScheduleGroup!focus!doOnFocus"] && $.__views.ScheduleGroup.addEventListener("focus", doOnFocus);
    _.extend($, exports);
}
var Alloy = require("alloy"), Backbone = Alloy.Backbone, _ = Alloy._;
module.exports = Controller;
PR: https://github.com/appcelerator/alloy/pull/245 test apps: * https://github.com/appcelerator/alloy/tree/master/test/apps/testing/ALOY-834 * https://github.com/appcelerator/alloy/tree/master/test/apps/ui/tabgroup Functional tests should be performed on both apps, with iOS and Android, and should be performed on one TiSDK greater than 3.1.0, and one TiSDK less than 3.1.0. Make sure all tests run without error. Additionally, the android tests should be able to launch the Android Menu with the menu button.
Verified fixed. TiSDK 3.2.0.v20131013140318 Alloy 1.3.0 Xcode 5 and iOS7 (device and emulator) Android Google Nexus One (4.1.2) and Android Emulator 2.3.3 Closing