Runtime event listener not being removed

It’s because your listener is local inside the create() function. It’s out of scope when you try to remove it in hide().
If you move the listener to outside of create() it should work.

I thought Runtime listeners could be removed anywhere. Also how is your Runtime Listener removed since it is in the function scene:show? 

The statements Runtime:addEventListener and Runtime:removeEventListener can be called anywhere since you are referring to the global object Runtime.

The reason why your code didn’t work is because your listener was declared *inside* the :create function which will only remain in scope inside that function. Once the :create function has finished the handle to that function disappears and there’s no way to reference it anymore. That’s why you need to move the listener outside the :create function to make it visible to the whole scene.

I recommend you Google “Lua variable scoping” to get a better understanding of how scoping works.
It’s essential to understand this when coding with Lua as it’s different from other languages.

Thanks for all your help.

I have the same issue. Is there a solution for this?

I’m not sure why it’s not removing the event listener with the storyboard.* API, however I’m using the new composer.* API and it removes the event listener as expected.

I just changed to composer but it did not help.

Very weird, I have the following composer.* API code which works as expected.

function scene:hide(event) local sceneGroup = self.view; local phase = event.phase; local parent = event.parent; if (phase == "will") then Runtime:removeEventListener("key", onAndroidKeyEvent); end end

What does your onAndroidKeyEvent function and EventListener look like?

It looks like this. I’m using the back key to close an overlay.

local onAndroidKeyEvent = function(event) local key = event.keyName; local phase = event.phase; if (key == "back") then if (phase == "down") then composer.hideOverlay(false, "slideDown"); end return true; end return false; end

Also what build are you using?

2259

Is that listener and function in:  function scene:create( event ) ?

The structure of my scene is as follows (stripping out a lot of code)
 

local composer = require("composer"); local scene = composer.newScene(); local onAndroidKeyEvent = function(event) local key = event.keyName; local phase = event.phase; if (key == "back") then if (phase == "down") then hideOverlay(false, "slideDown"); end return true; end return false; end -- ------------------------------------------------------------------------------- function scene:create(event) local sceneGroup = self.view -- create stuff end function scene:show(event) local sceneGroup = self.view; local phase = event.phase; local parent = event.parent; if (phase == "will") then Runtime:addEventListener("key", onAndroidKeyEvent); end end function scene:hide(event) local sceneGroup = self.view; local phase = event.phase; local parent = event.parent; if (phase == "will") then Runtime:removeEventListener("key", onAndroidKeyEvent); end end function scene:destroy(event) local sceneGroup = self.view; end -- ------------------------------------------------------------------------------- scene:addEventListener("create", scene); scene:addEventListener("show", scene); scene:addEventListener("hide", scene); scene:addEventListener("destroy", scene); -- ------------------------------------------------------------------------------- return scene;

This is the structure of my scene which does not remove the “key” listener. Do you have any ideas why this would not work?

local composer   = require(“composer”);

local scene      = composer.newScene();


function scene:create(event)

    local sceneGroup = self.view

    

    local onAndroidKeyEvent = function(event)

        local key = event.keyName;

        local phase = event.phase;

        if (key == “back”) then

            if (phase == “down”) then

                hideOverlay(false, “slideDown”);

            end

        

            return true;

        end

        return false;

    end

    

    Runtime:addEventListener(“key”, onAndroidKeyEvent);

    – create stuff

end

function scene:show(event)

    local sceneGroup = self.view;

    local phase = event.phase;

    local parent = event.parent;

    if (phase == “will”) then

        –

    end

end

function scene:hide(event)

    local sceneGroup = self.view;

    local phase = event.phase;

    local parent = event.parent;

    if (phase == “will”) then

        Runtime:removeEventListener(“key”, onAndroidKeyEvent);

    end

end

function scene:destroy(event)

    local sceneGroup = self.view;

end

It’s because your listener is local inside the create() function. It’s out of scope when you try to remove it in hide().
If you move the listener to outside of create() it should work.

I thought Runtime listeners could be removed anywhere. Also how is your Runtime Listener removed since it is in the function scene:show? 

The statements Runtime:addEventListener and Runtime:removeEventListener can be called anywhere since you are referring to the global object Runtime.

The reason why your code didn’t work is because your listener was declared *inside* the :create function which will only remain in scope inside that function. Once the :create function has finished the handle to that function disappears and there’s no way to reference it anymore. That’s why you need to move the listener outside the :create function to make it visible to the whole scene.

I recommend you Google “Lua variable scoping” to get a better understanding of how scoping works.
It’s essential to understand this when coding with Lua as it’s different from other languages.

Thanks for all your help.

I don’t want to question a jedi forum member :), but is that possibly true? I can do scene.foo = “bar” inside sceneCreate then scene.foo is available in every other function. Isn’t Runtime an “upper level” object just like scene (but even up higher)?

And when I do Runtime:addEventListener I’m not getting a handle back; I assumed Corona was taking care of that behind the scene, which is why you have to do a remove using the same parameters as the add.

When using Composer, how are you supposed to do Runtime:addEventListener outside of a function since everything runs based on functions?

 Jay

PS - I discovered this thread because I’m having problems with a Runtime event listener that won’t go away. :slight_smile: