如何在Android/iOS中释放组件
我在Android中的表单上动态创建了一个如何在Android/iOS中释放组件,android,ios,delphi,components,firemonkey,Android,Ios,Delphi,Components,Firemonkey,我在Android中的表单上动态创建了一个TEdit: edit := TEdit.Create(Self); 我想使用edit.free释放它,但它仍然在表单上 此代码在win32上运行良好,但在Android上失败 这似乎不仅适用于TEdit,也适用于使用Android或iOS的任何组件。在移动平台上,使用ARC管理生命周期。只有当对象没有引用时,对象才会被销毁。您的对象具有对它的引用,特别是来自其父对象的引用 现在可以使用DisposeOf强制销毁对象。详情如下: 但是,我怀疑更好的解决
TEdit
:
edit := TEdit.Create(Self);
我想使用edit.free
释放它,但它仍然在表单上
此代码在win32上运行良好,但在Android上失败
这似乎不仅适用于TEdit,也适用于使用Android或iOS的任何组件。在移动平台上,使用ARC管理生命周期。只有当对象没有引用时,对象才会被销毁。您的对象具有对它的引用,特别是来自其父对象的引用 现在可以使用
DisposeOf
强制销毁对象。详情如下:
但是,我怀疑更好的解决方案是删除对对象的引用。将其从容器中取出。例如,将其父对象设置为nil 更新为10.4
Delphi 10.4 Sydney跨所有平台统一内存管理,并删除了ARC编译器。换句话说,所有平台现在都遵循与Windows平台相同的内存管理规则
dispeof
vsFree
在经典(非ARC)编译器中
对经典编译器调用DisposeOf
进行处理,在功能上表现相同Free
仅用于向后兼容,在新代码(不必与ARC编译器保持兼容)中,首选使用DisposeOf
Free
- 在现有代码中,
不必更改为DisposeOf
Free
原始答案,对ARC编译器有效: 简短回答 在Delphi ARC编译器(当前为Android和iOS)下发布任何
TComponent
子体对象时,应遵循两条规则:
- 无论对象是否拥有所有者,都必须使用
DisposeOf
- 在析构函数中或在调用
后不久引用未超出范围的情况下,对象引用也应设置为DisposeOf
(陷阱中的详细说明)nil
DisposeOfAndNil
方法可能很有吸引力,但ARC使其比旧的FreeAndNil
方法复杂得多,我建议使用普通的DisposeOf-nil
顺序来避免其他问题:
Component.DisposeOf;
Component := nil;
虽然在许多情况下,即使不遵守上述规则,代码也能正常工作,但这样的代码相当脆弱,很容易被在看似无关的地方引入的其他代码破坏
ARC内存管理上下文中的DisposeOf
DisposeOf
断开圆弧。它违反了ARC的黄金法则任何对象引用都可以是有效的对象引用或nil,并引入了第三状态-已处置的“僵尸”对象引用
任何试图理解ARC内存管理的人都应该看看类似于添加的dispeof
,它只是解决了特定于Delphi的框架问题,而不是真正属于ARC本身的概念
为什么Delphi ARC编译器中存在DisposeOf?
t组件
类(及其所有子类)的设计考虑了手动内存管理。它使用的通知机制与ARC内存管理不兼容,因为它依赖于中断析构函数中的强引用循环。由于TComponent
是Delphi框架所依赖的基类之一,因此它必须能够在ARC内存管理下正常工作
除了自由通知
机制之外,Delphi框架中还有其他类似的设计适合于手动内存管理,因为它们依赖于中断析构函数中的强引用循环,但这些设计不适合于ARC
DisposeOf
方法允许直接调用对象析构函数,并允许此类遗留代码与ARC一起使用
这里必须注意一点。任何使用或继承自TComponent
的代码都会在正确的ARC管理环境中自动成为遗留代码,即使您现在就编写
引用艾伦·鲍尔的博客
那么,脱节还能解决什么呢?这在各种各样的人中很常见
Delphi框架(包括VCL和FireMonkey),用于将
构造函数内的通知或列表管理代码,以及
类的析构函数。TComponent的所有者/所有者模型是一个关键
这种设计的例子。在本例中,现有组件
框架设计依赖于许多活动,而不是简单的“资源”
“管理”将发生在析构函数中
TComponent.Notification()就是这样一个关键的例子。在这个
在这种情况下,“处置”组件的正确方法是使用DisposeOf。A.
t组件派生通常不是一个瞬态实例,而是一个瞬态实例
一种寿命较长的物体,周围还有一个完整的生命系统
构成形状、框架等的其他构件实例
和数据模块。在这种情况下,使用DisposeOf是合适的
处置是如何运作的
为了更好地理解调用DisposeOf
时到底发生了什么,有必要了解Delphi对象销毁过程是如何工作的
在ARC和非ARC Delphi编译器中释放对象涉及三个不同的阶段
析构函数Destroy
方法链Component.Free
->立即执行阶段1->2->3
使用ARC编译器释放对象
或Component.Free
->减少对象引用计数,后跟a)或b)Component:=nil
- a)如果对象参考c
procedure ComponentLeak; var Edit: TEdit; Menu: TPopupMenu; begin Edit := TEdit.Create(nil); Menu := TPopupMenu.Create(nil); Edit.PopupMenu := Menu; // creating strong reference cycle Menu.Free; // Menu will not be released because Edit holds strong reference to it Edit.Free; // Edit will not be released because Menu holds strong reference to it end;
type TFoo = class(TObject) public a: TObject; end; var foo: TFoo; b: TObject; procedure DoDispose; var n: integer; begin b := TObject.Create; foo := TFoo.Create; foo.a := b; foo.DisposeOf; n := b.RefCount; // foo is still alive at this point, also keeping b.RefCount at 2 instead of 1 end; procedure DoFree; var n: integer; begin b := TObject.Create; foo := TFoo.Create; foo.a := b; foo.Free; n := b.RefCount; // b.RefCount is 1 here, as expected end;
type TFoo = class(TObject) public s: string; d: array of byte; o: TObject; end; var foo1, foo2: TFoo; procedure DoSomething; var s: string; begin foo1 := TFoo.Create; foo1.s := 'test'; SetLength(foo1.d, 1); foo1.d[0] := 100; foo1.o := TObject.Create; foo2 := foo1; foo1.DisposeOf; foo1 := nil; s := IntToStr(foo2.o.RefCount) + ' ' + foo2.s + ' ' + IntToStr(foo2.d[0]); // output: 1 test 100 - all inner managed references are still alive here, // and will live until foo2 goes out of scope end;
destructor TFoo.Destroy; begin s := ''; d := nil; o := nil; inherited; end;
type TChild = class; TParent = class(TObject) public var Child: TChild; end; TChild = class(TObject) public var Parent: TParent; constructor Create(AParent: TParent); end; constructor TChild.Create(AParent: TParent); begin inherited Create; Parent := AParent; end; var p: TParent; begin p := TParent.Create; p.Child := TChild.Create(p); p.DisposeOf; p := nil; end;
TChild = class(TObject) public [weak] var Parent: TParent; constructor Create(AParent: TParent); end;
- a)如果对象参考c