I just started developing a mobile app which has two forms, FRM_Main
(Main Form) and FRM_Party
(Party Form). We can open FRM_Party
from FRM_Main
by clicking on an Image. Code on Image is:
procedure TFRM_Main.IMAGE_PartyClick(Sender: TObject);
begin
FRM_Party := TFRM_Party.Create(Application);
FRM_Party.Show;
end;
Now, when FRM_Party
calls the OnActivate
event, I am loading some data in a TMSFMXTableView
. That code is:
procedure TFRM_Party.FormActivate(Sender: TObject);
var
TableView : TTMSFMXTableViewItem;
I : Integer;
begin
if Class_My_Pro_and_func.Func_DataBaseConnection then // Checks wethere database connection is active or not if not then it connect with database and returns bool value.
Begin
UniQuery.Close;
UniQuery.SQL.Clear;
UniQuery.SQL.Text := 'select * from db_stock.tbl_party where Reg_ID = :Reg_ID and Party_Delete <> :Party_Delete order by Party_Name ';
UniQuery.ParamByName('Reg_ID').AsInteger := d_Glob_Reg_ID;
UniQuery.ParamByName('Party_Delete').AsString := 'F';
UniQuery.Open;
TABLEVIEW_Party.BeginUpdate;
if UniQuery.RecordCount > 0 then
begin
for I := 1 to UniQuery.RecordCount do
begin
TableView := TABLEVIEW_Party.Items.Add;
TableView.Caption := UniQuery.Fields[1].AsString;
TableView.Description := UniQuery.Fields[2].AsString + ' = ' + UniQuery.Fields[3].AsString;
TABLEVIEW_Party.EndUpdate;
UniQuery.Next;
end;
end
else
ShowMessage('No recored Found.');
End
end;
On FRM_Party
is a Back button which takes the user to FRM_Main
. This button code is:
procedure TFRM_Party.BTN_Party_BackClick(Sender: TObject);
begin
try
UniQuery.Connection.Close; // Closing Query connection
DB_Connection.Disconnect; // Disconnecting database
FreeAndNil(FRM_Party);
Close;
except
on E: Exception do
ShowMessage(E.Message);
end;
end;
Apart from the above code, nothing else is written on FRM_Party
.
Now, the thing is that when I am running the application on mobile and opening/closing FRM_Party
again and again, the first 4 times FRM_Party
works very nice, but on the fifth time FRM_Party
opens properly, but when closed the app hangs. I tried so many times by closing and opening the app. Every time the result is the same.
Can anyone help me?
In your OnActivate
handler, your calls to BeginUpdate()
and EndUpdate()
on TABLEVIEW_Party
are unbalanced if UniQuery.RecordCount
is not exactly 1. You are calling BeginUpdate()
before entering the loop, which is fine, but then you are calling EndUpdate()
inside the loop, thus calling it a different number of times than you call BeginUpdate()
. You need to move those calls to the same level, eg:
procedure TFRM_Party.FormActivate(Sender: TObject);
var
TableView : TTMSFMXTableViewItem;
I : Integer;
begin
if not Class_My_Pro_and_func.Func_DataBaseConnection then
Exit;
UniQuery.Close;
UniQuery.SQL.Text := 'select * from db_stock.tbl_party where Reg_ID = :Reg_ID and Party_Delete <> :Party_Delete order by Party_Name ';
UniQuery.ParamByName('Reg_ID').AsInteger := d_Glob_Reg_ID;
UniQuery.ParamByName('Party_Delete').AsString := 'F';
UniQuery.Open;
if UniQuery.RecordCount > 0 then
begin
TABLEVIEW_Party.BeginUpdate;
try
for I := 1 to UniQuery.RecordCount do
begin
TableView := TABLEVIEW_Party.Items.Add;
TableView.Caption := UniQuery.Fields[1].AsString;
TableView.Description := UniQuery.Fields[2].AsString + ' = ' + UniQuery.Fields[3].AsString;
UniQuery.Next;
end;
finally
TABLEVIEW_Party.EndUpdate;
end;
end
else
ShowMessage('No record Found.');
end;
Also, in your back button's OnClick
handler, you are calling Close()
on FRM_Party
after calling FreeAndNil(FRM_Party)
.
On mobile platforms prior to RAD Studio 10.4, object lifetime is managed by ARC. Calling FreeAndNil(FRM_Party)
will not actually free the FRM_Party
object, it will simply set the FRM_Party
variable to nil
. The object is not freed because Application
still has an active reference to it.
But in RAD Studio 10.4 onwards, ARC is no longer used, so calling FreeAndNil(FRM_Party)
will actually destroy the object. So calling Close()
after afterwards will crash your code.
The correct way to free a TForm
when it is closed is to use its OnClose
event instead, eg:
procedure TFRM_Party.FormDestroy(Sender: TObject);
begin
If FRM_Party = Self then
FRM_Party := nil;
end;
procedure TFRM_Party.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := TCloseAction.caFree;
end;
procedure TFRM_Party.BTN_Party_BackClick(Sender: TObject);
begin
UniQuery.Connection.Close;
DB_Connection.Disconnect;
Close;
end;