Alloy createController не освобождается из памяти

Недавно я проводил анализ памяти в одном из своих приложений. Приложение сделано для платформы Android. На двух экранах я наблюдаю утечку.

Без проверки, я удалил весь свой код и оставил только вызов $.screenName.open() на обоих контроллерах, и способ их вызова:

Alloy.createController(screenToLaunch, payloadJson);

Внутри соответствующих контроллеров присутствовал вызов open(). Я использую DDMS и делаю анализ кучи.

Прежде чем открыть контроллер A, я несколько раз нажимал кнопку GC, чтобы получить стабильное выделенное чтение. После этого я запускаю контроллер A и нажимаю кнопку «Назад», чтобы закрыть его. Теперь, когда я несколько раз нажимаю на вызов GC, каждый раз разница составляет 60 КБ.

Я не сохраняю ссылку createController ни в одной глобальной переменной. Любая идея относительно того, почему он ведет себя таким образом?

Обновлено: HPROF Разница

Выше показана разница HPROF между открытием и закрытием контроллера. Я не использую никаких вызовов БД, но вижу, что выполняется много вызовов, связанных с БД. Я думаю, возможно, фреймворк использует эти вызовы для своего внутреннего функционирования.


person Soumya    schedule 05.05.2016    source источник
comment
Можете ли вы поделиться кодом этого, поскольку это может быть связано со многими причинами?   -  person Prashant Saini    schedule 06.05.2016
comment
Привет, Прашант, код JS содержит только вызов $.controllerName.open(), а XML содержит прокрутку с несколькими двумя внутренними представлениями.   -  person Soumya    schedule 06.05.2016
comment
Поделитесь несколькими снимками экрана и конфигурациями вашей среды, так как разница в 60 КБ не кажется слишком большой и может зависеть от устройства или вашей среды разработки, потому что я уверен, что вы уже знаете о способах очистки памяти. Вы используете Mac OS или Windows или Linux ..?   -  person Prashant Saini    schedule 07.05.2016
comment
Мне еще предстоит запустить XCode Instruments в коде, чтобы попытаться определить, если таковые имеются. Я не очищаю какой-либо прокси, и он задерживается, для которого происходит утечка. Я занимаюсь разработкой на Mac OS. Что касается GC, я знаю, что это зависит от системы, поэтому после нескольких нажатий кнопки GC я жду несколько минут, прежде чем снимать показания. Нужны скрины для монитора (инструмент андроид) с чтением?   -  person Soumya    schedule 09.05.2016
comment
Я добавил разницу HPROF между двумя состояниями и разницу объектов.   -  person Soumya    schedule 09.05.2016


Ответы (2)


Я использую эту архитектуру для контроллеры (UI.Windows) и работает очень хорошо.

  • Открытое окно: Alloy.createController('name_controller').getView().open();

Очистка контроллеров Alloy

person Jagu    schedule 05.05.2016
comment
Поэтому вместо вызова win.open() внутри name_controller вы выполняете getVoew().open(). Помогает ли освобождение объекта контроллера, когда я нажимаю клавишу «Назад» и закрываю name_controller? Может быть, я могу изменить код и посмотреть, работает ли это. - person Soumya; 06.05.2016
comment
Это не должно быть проблемой. - person Shawn; 06.05.2016
comment
Правильно, это то, что я думал так. Я даже устанавливаю для переменной значение null, в котором хранится ссылка на контроллер. Я предполагаю, что мне нужно использовать инструменты XCode, чтобы понять это, или, возможно, мне понадобится провести анализ HPROF. - person Soumya; 06.05.2016

Это мой метод очистки для всех контроллеров и виджетов:

какой-то вид.js

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

data.button = Alloy.createController('button',{
    title:'button'
}).getView();

 $.view.cleanup = function() {

    $.destroy();

    $.off();

    data.button.cleanup();

    $ = data = args = null;
};

кнопка.js

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

data.click = function() { ... };

$.view.addEventListener('click',data.click);

$.view.cleanup  = function() {

    $.destroy();

    $.off();

    $.view.removeEventListener('click',data.click);

    $ = data = args = null;
};

Я создал глобальную функцию для вызова метода очистки и удаления его содержимого для каждого дочернего элемента контроллеров:

ОБНОВЛЕНИЕ

добавлен оператор удаления и инструкция try

exports.unset = function(view) {

    if(view) {

        if(view.children && view.children.length) {

            for(var i in view.children) try { util.unset(view.children[i]);
            } catch(e) {}

            view.removeAllChildren();
        }

        if(view.views && view.views.length) for(var i = view.views.length; i > 0; i--) if(view.views[i-1]) {

            if(view.removeView) view.removeView(i-1);

            try { util.unset(view.views[i-1]);
            } catch(e) {}
        }

        if(view.cleanup) try { view.cleanup();
        } catch(e) {}

        view = null;

        delete view;
    }
};
person Ricardo Pereira    schedule 06.05.2016
comment
Я вставил код $.off и $.destroy. Но все же он сохраняет объекты. Мне нужно попытаться создать из него образец приложения, а затем протестировать его. - person Soumya; 06.05.2016
comment
когда вы удаляете представление или запускаете метод очистки, он все еще существует в соответствии с моими журналами проекта, после установки представления равным нулю, я больше не могу использовать его или его методы, но я думаю, что он удаляется из памяти только после сборка мусора на андроиде, на iOS я слышал про ARC, но не уверен, что это такое. Я хотел бы лучше понять эти вопросы «Управление памятью», поскольку мое самое большое приложение использует только одно окно, но сильно меняет его содержимое с большим количеством представлений и виджетов, этот код был моим лучшим подходом. - person Ricardo Pereira; 10.05.2016
comment
Это тот же подход, которого я придерживаюсь. После удаления представлений я явно установил для них значение null. Что касается GC в Android, он срабатывает, когда возникает нехватка памяти или всякий раз, когда алгоритм GC решит его запустить. Еще один интересный фрагмент, который я нашел в вашем коде, — установка $ на null и args на null. Нужны ли эти два? Разве это не будет сделано самим фреймворком? - person Soumya; 10.05.2016
comment
Я не знаю, будет ли это делать фреймворк, но на всякий случай, так как я использую все свои методы и свойства контроллера внутри 'var data = {};' и я всегда использую аргументы, в конце всех моих контроллеров я использую это: '$ = data = args = null;' - person Ricardo Pereira; 10.05.2016
comment
Я думаю, будет лучше присвоить переменной args значение null. Внесу изменения и посмотрю, поможет ли это, и оставлю эту тему опубликованной. - person Soumya; 10.05.2016
comment
После установки некоторых свойств объекта в значение null или undefined запуск «Object.keys(myObj).length» возвращает то же значение, что и это свойство все еще существует, поэтому после того, как я установил его в значение null, в этой «неустановленной» глобальной функции, которую я добавил : удалить представление; - person Ricardo Pereira; 14.05.2016
comment
Я обновил неустановленную функцию в своем ответе: добавил оператор удаления и оператор попытки. - person Ricardo Pereira; 14.05.2016