What are the best practises for data binding in appcelerator titanium and avoid memory crash

You must Login before you can answer or comment on any questions.

I have been using custom events to handle data binding with titanium appcelerator using an event called RefreshComp for a given object id (unique across all objects) and attribute passing the new value. This new value could come from a push notification , an object beeing edited in the iphone app that you want to propagate to all the comps etc...

Titanium.App.fireEvent(RefreshComp, {
        refreshid : objectId + '-' + attribute,
        value : newvalue
     });
and
function registerEvent(objectId,attribute,eventHandler){
        Titanium.App.addEventListener(RefreshComp, function(e) {
            if((e.refreshid === (objectId + '-' + attribute))) {
                eventHandler(comp, e.value);
            }
        });
    }
and then your eventHandler function could be as simple as
function eventHandler(comp,newvalue){
        comp.value = newvalue;
    }
or more complicated (like changing background etc...)

My point is that this causes the comp to be bound to the global context causing the object not to be release. I have tried to attach custom event to the component itself but it does not work. As a result I am getting the application that is crashing with

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
    [TiViewProxy _hasListeners:] (TiViewProxy.m:1170)
    [TiUITableViewCell setHighlighted:animated:] (TiUITableView.m:80)
because the binding refer to a component still in memory on the IOS side but then when TiViewProxy.m calls for the parent function in _hasListeners , it is not able to find the parent in memory that does not have any associated object and the parent has been removed form the memory

I have googled and look at the git rep of appcelerator but there are no example of this.

2 Answers

Hello,

if you want to share data across your app, you should be using Ti.App properties. Check this document about this.

Just remember that you can only share simply values this way. If you want to share something more complex, you should be using a database.

Best,

Mauro

— answered 1 year ago by Mauro Parra
answer permalink
1 Comment
  • Hey Marco, thanks a lot for your response but I am not sure I understand your answer, what I am asking for relates to data binding and how do you get the information propagated automatically from once component to another (because of a push notification or some object being edited) of course if I restart the app or refresh the list all the comps will be reconstructed so they will all display the same thing but if you want to modify components that are already displayed right now I am using events but it is causing some memory issues for the reason I have mentioned

    — commented 1 year ago by jean-baptiste pringuey

hi jean..

please try this

var win = Ti.UI.createWindow({
    fullscreen:false,
    layout: 'vertical'
});
var btn = Ti.UI.createButton({
    title: 'Update This'
});
var btn2 = Ti.UI.createButton({
    title: 'Open New Window'
});
btn2.addEventListener('click',function(e){
    var win2 = Ti.UI.createWindow({
        fullscreen: false
    });
    var btn3 = Ti.UI.createButton({
        title: 'Update window behind!'
    });
    btn3.addEventListener('click',function(e){
        Ti.App.fireEvent('update:this',{
            title: 'Congratulations'
        });
    });
    win2.add(btn3);
    win2.open();
});
Ti.App.addEventListener('update:this',function(e){
    btn.title = e.newTitle;
});
win.add(btn);
win.add(btn2);
win.open();
This demo will update the window behind when he click the btn3... i hope this helps.

— answered 1 year ago by Ken Crucillo
answer permalink
6 Comments
  • Hey Ken,

    that is exactly what I am going and it works, the problem is that if the button is then tied to the global context and we have memory leaks and a risk of memory issue, the ideal solution would be to replace

    Ti.App.addEventListener('update:this',function(e){
        btn.title = e.newTitle;
    });
    by
    btn.addEventListener('update:this',function(e){
        btn.title = e.newTitle;
    });
    so the memory is released once the button comps is not displayed anymore but it does not work :-(

    thanks for the help

    — commented 1 year ago by jean-baptiste pringuey

  • hi again.. i dont know if it will work in this way... try to pass the button through the window then fire that event...

    var win = Ti.UI.createWindow({
        fullscreen:false,
        layout: 'vertical'
    });
    var btn = Ti.UI.createButton({
        title: 'Update This'
    });
    var btn2 = Ti.UI.createButton({
        title: 'Open New Window'
    });
    btn2.addEventListener('click',function(e){
        var win2 = Ti.UI.createWindow({
            fullscreen: false,
        btnHndlr: btn   //pass the btn to the window then fire it to the other
        });
        var btn3 = Ti.UI.createButton({
            title: 'Update window behind!'
        });
        btn3.addEventListener('click',function(e){
            win.btnHndlr.fireEvent('update:this',{
                title: 'Congratulations'
            });
        });
        win2.add(btn3);
        win2.open();
    });
    btn.addEventListener('update:this',function(e){
        btn.title = e.newTitle;
    });
    win.add(btn);
    win.add(btn2);
    win.open();
    It's hard to anticipate what you want coz.. of limited info.. like how you generate the window.. how you create the btns.. etc... But i hope in this idea.. you can have a workaround now...

    — commented 1 year ago by Ken Crucillo

  • i mean..

    //sorry typo
    win2.btnHndlr.fireEvent('update:this',{
        title: 'Congratulations'
    });

    — commented 1 year ago by Ken Crucillo

  • Show 3 more comments

Your Answer

Think you can help? Login to answer this question!