0
votes

I am having trouble understanding the back button behavior in my alloy application in android. The scenario is this:

I am loading a widget in one of my windows to which I pass some parameters to use. I am retrieving these arguments in the standard way:

var args = arguments[0] || {};

On window close, I am setting the args to null. Now, this works fine as long as I close the window using my close button. args is set to null, and re-instantiated when I open the window again.

When I close the window with back button, args is set to null, but is never re-instantiated once I open the window again, and remains null. I have checked this with both heavyweight and light windows.

What all things does back button do? How can I enable re-instantiation of all the arguments again on opening the window?

Code: index.xml

<Alloy>
    <Window id="myWin" class="container">
        <View layout="vertical">
            <Require type="widget" src="myWidget" id="myWidget" title='mainWindow' close='mainWindow' />
        </View>
    </Window>
</Alloy>

index.js:

// setting args to null on window close
$.myWin.addEventListener('close', function () {
    $.myWidget.resetData();
});

Inside myWidget's controller, widget.js:

var args = arguments[0] || {};

// sets args to null
function resetData() {
    args = null;
}

exports.resetData = resetData;

The above code does not re-initiate args once set to null (when we close window with back button). If however, I export args and set it to null in window controller, it shows there that args is null, but args has all the data once we re-open the window again even though it is not initiated again.

Code: index.js

$.myWin.addEventListener('close', function () {
    $.myWidget.args = null;
});

Inside myWidget's controller, widget.js:

exports.args = args;

What exactly is going on here?

1
Can you share some more code of how you are closing the window and how you are setting the args to null? - Prashant Saini
Why do you need to null the args? AFAIK when we close the window, all of the child elements are removed from memory as well and so no need to null the args unless the args are allocated to a global variable. - Prashant Saini
Actually, args is set as a global variable in widget controller. Now, I can't change its scope, as the problem again is failing of re-initialization. So, if I change its scope to local, next time I am not getting any arguments which I need. - learner123
If you need its arguments, then instead of saving them in global variable, you can save them in a commonjs file. See my edited answer, I have included a way to save and access data in a common js file. - Prashant Saini
Yes, the updated method will work. But the problem is I still need to know the behavior of the back button. There are some more places I am using such logic, like setting images property of imageView dynamically. But it is failing after using back button once, and throwing errors like this: [ERROR] TiApplication: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference. Not sure how to move ahead :( - learner123

1 Answers

1
votes

If you are using the window's onClose event to null the args, then I suggest you to do this inside a single function like this:

win.xml

<Alloy>
    <Window onAndroidback="close">
        <ActionBar platform="android" onHomeIconItemSelected="close"></ActionBar>

        <Button title="Close Window" onClick="close" />
    </Window>
</Alloy>

win.js

function close() {
    args = null;
    $.win.close();
}
  • Note that now you do not need onClose event of window as you are calling the same function upon back button press and normal close button or even on back arrow of action bar, so this will make sure that same thing will happen in every case.

Hope it will help you, or if not then please share some code. Good Luck!!!


As per your last comment, here's how you can access your widget's data in any controller file without using global variable.

app/lib/foo.js:

// For a classic Titanium project, save the file to 'Resources/foo.js'
var data = {};
function setData (obj){
    data = obj;
}
function getData () {  
    return data;
}

// The special variable 'exports' exposes the functions as public
exports.setData = setData;
exports.getData = getData;

app/views/index.xml

<Alloy>
    <Window backgroundColor="blue">
        <Label onClick="openWindow">Open the Red Window!</Label>
    </Window>
</Alloy>

app/controllers/index.js

var foo = require('foo');
foo.setData({foobar: 42});

function openWindow () {
    Alloy.createController('win2').getView().open();
}

$.index.open();

app/views/win2.xml

<Alloy>
    <Window backgroundColor="red">
        <Label id="label">I am a red window.</Label>
    </Window>
</Alloy>

app/controllers/win2.js

var foo = require('foo');
$.label.text = foo.getData().foobar;

You can do the exact same thing with your widget code. Hope it helps!