#android #ios #delphi #firemonkey
#Android #delphi #автоматический подсчет ссылок #firemonkey
Вопрос:
Изнутри обработчика событий самого элемента управления я хотел бы удалить и освободить его.
Типичный вариант использования TFmxObject.Release
, не так ли? Однако, похоже, что он работает только под Windows, но не под Android, и этот метод в любом случае устарел.
Я знаю, что «не работает» — это не очень хорошее описание проблемы, но в настоящее время я не могу отладить его под Android. В Windows я вижу, что обработчик событий продолжается корректно после .Release
и после его завершения выполняется мое сообщение журнала внутри моего деструктора controls. Под Android приложение зависает.
Когда я использую .Free
вместо этого, он по-прежнему работает под Windows (деструктор происходит немедленно, но обработчик не обращается к элементу управления после освобождения), а в Android видимых проблем нет, но деструктор никогда не вызывается, поэтому у меня утечка.
.DisposeOf
Эффект такой же, как и при .Release
— Windows ok, Android зависает.
Я тоже пробовал MyParent.RemoveComponent(MyControl)
, но все это не помогло.
Что еще мне нужно сделать, чтобы освободить все ссылки, чтобы ARC мог выполнять свою работу? Или как еще?
Комментарии:
1. Если вы используете Delphi 10.2 Tokyo, вы могли бы использовать TThread . Принудительно выполнить код позже.
TThread.ForceQueue(nil, procedure begin // Dispose of the control end);
2. Это именно то, что
.Release
делает. Кажется, что на Android это выполняется немедленно, а не позже, и именно поэтому a.DisposeOf
без очереди ведет себя так же. Я только что проверил это сам…3. Я полагаю, еще одна ошибка в RTL. Пожалуйста, отправьте отчет QP.
4. Можете ли вы решить эту проблему, создав анонимный поток и внутри утилизировать элемент управления в методе очереди?
5. @DalijaPrasnikar: неважно, я нашел один: RSP-17841 TThread. ForceQueue не работает в Android
Ответ №1:
TFmxObject.Release
используется TThread.ForceQueue
внутри, и в настоящее время это не работает под Android (см. Обсуждение выше).
В качестве обходного пути рабочая кроссплатформенная версия для освобождения объекта из его обработчика событий будет
procedure TForm.CloseBtnClick(Sender: TObject);
begin
Parent := nil;
TThread.CreateAnonymousThread(
procedure
begin
TThread.Queue(nil,
procedure
begin
Self.DisposeOf;
end);
end).Start;
end;
Важно иметь в виду, что вы не должны сохранять какие-либо другие ссылки на отпущенный вами элемент управления, иначе у вас могут возникнуть проблемы в будущем.
Обновление для 10.4 и более новых версий:
Начиная с 10.4 и унифицированное управление памятью DisposeOf
теперь эквивалентно Free
на всех платформах и Self.DisposeOf
может быть заменено Self.Free
.
Комментарии:
1. Я бы использовал
TThread.Queue()
вместоTThread.Synchronize()
2. Это была идея обходного пути @LURD, и мне это не понравилось, но вы убедили меня высококачественным проверенным кодом, спасибо 🙂
3. Извините, я не ответил раньше … был занят … ваш вопрос был в порядке, хотя теперь он еще лучше. Спасибо за редактирование моего ответа 🙂
4. quality.embarcadero.com/browse/RSP-17841 говорит , что эта проблема была исправлена в версии 10.3 Rio