Reputation: 73
I’m having problems of performance speed in an Android app in Delphi XE7 with Firemonkey using JSON XSuperObject and data retrieved from a web API.
My scenario is a system ranking table that creates 29 controls at runtime with each iteration, sometimes the number of players should be more than 90 so for each iteration (90 * 27) it create 2610~ controls at runtime. Tested on a Windows platform it took 3 secs., but in a mobile platform with Android, it took 17 secs. I’m aware that it would affect to the performance of the app, but I don’t knew of the significant difference of load time of Windows and Android.
So is there any way to reduce the load time or optimize the code below for a best performance?, thanks.
Kind Regards.
{Controls to create at runtime;
1 TLayout as parent of the controls (1 control).
1 TLine at bottom of TLayout to separate layouts (+1 control)
1 TPanel with a TImage for the player avatar and a TLabel for the player name (+3 controls).
1 TPanel with a TButton to display details (+2 controls).
1 TPanel with a THorzScrollBox containing 10 TLabels inside of 10 TRectangle as parent to scroll and display the points of the round (+22 controls).
Overall of 29 controls to create at runtime in each iteration.}
procedure TForm1.RankingClick(Sender: TObject);
var
JsonObjHC: ISuperObject;
JsonArrHC: ISuperArray;
JsonStrHC, URL_IRkC, Pais: String;
Retriever: TIdHTTP;
x, z: integer;
Before, After, Total: TDateTime;
begin
URL_IRkC := 'web api URL here ….';
Retriever := TIdHTTP.Create(nil);
try
JsonStrHC := Retriever.Get(URL_IRkC);
finally
Retriever.DisposeOf;
end;
JsonArrHC := SA(JsonStrHC);
Before := Time; // to check seconds before loop starts
LytMainRk.BeginUpdate; //Main layout that contains all controls.
for x := 0 to JsonArrHC.Length-1 do
begin
JsonObjHC := JsonArrHC.O[x];
// proceddure that creates controls in each iteration
Ranking_Table (JsonObjHC.S['Image'], JsonObjHC.S['Name'], JsonObjHC.I['R1'], JsonObjHC.I['R2'], JsonObjHC.I['R3'], JsonObjHC.I['R4'], JsonObjHC.I['R5'], JsonObjHC.I['R6'], JsonObjHC.I['R7'], JsonObjHC.I['R8'], JsonObjHC.I['R9'], JsonObjHC.I['R10'], x, z);
inc(z, 28);
end;
LytMainRk.EndUpdate;
Total := Before - After;
SecondsBetween(ShowMessage(DateToStr(Total)); // seconds after loop finishes, 3 secs. on Windows, 17 secs. on Android
end;
procedure TForm1.Ranking_Table(Avatar, NameP: String; R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, x, z: integer);
var
RectHC_R1, RectHC_R2, RectHC_R3, RectHC_R4, RectHC_R5, RectHC_R6, RectHC_R7, RectHC_R8, RectHC_R9, RectHC_R10: TRectangle;
PanelHC, PanelHC1, PanelHC2: TPanel;
ImageAvatarHC: TImage;
LineaHC: TLine;
LNameHC, LabelHC_R1, LabelHC_R2, LabelHC_R3, LabelHC_R4, LabelHC_R5, LabelHC_R6, LabelHC_R7, LabelHC_R8, LabelHC_R9, LabelHC_R10: TLabel;
LayoutHC: TLayout;
BotonHC: TButton;
HorzScrollBoxHC: THorzScrollBox;
begin
LayoutHC := TLayout.Create(Self);
LayoutHC.Name := 'LayoutHC' + x.ToString;
LayoutHC.Align := TAlignLayout.Top;
LayoutHC.Margins.Left := 6;
LayoutHC.Margins.Right := 6;
LayoutHC.Margins.Top := 0;
LayoutHC.Position.Y := z;
LayoutHC.Height := 28;
LayoutHC.Parent := LyHistorialC;
LineaHC := TLine.Create(Self);
LineaHC.Name := 'LineaHC' + x.ToString;
LineaHC.Align := TAlignLayout.MostBottom;
LineaHC.LineType := TLineType.Top;
LineaHC.Height := 1;
LineaHC.Stroke.Color := $FF708090;
LineaHC.Stroke.Thickness := 1;
LineaHC.Parent := LayoutHC;
PanelHC := TPanel.Create(Self);
PanelHC.Name := 'PanelHC_' + x.ToString;
PanelHC.Align := TAlignLayout.MostLeft;
PanelHC.Width := 126;
PanelHC.Parent := LayoutHC;
ImageAvatarHC := TImage.Create(Self);
ImageAvatarHC.Name := ' ImageAvatarHC ' + x.ToString;
ImageAvatarHC.Align := TAlignLAyout.Left;
ImageAvatarHC.Margins.Left := 4;
ImageAvatarHC.Margins.Right := 2;
ImageAvatarHC.Width := 28;
load_image_from_resource(ImageAvatarHC, Avatar);
ImageAvatarHC.Parent := PanelHC;
LNameHC := TLabel.Create(Self);
LNameHC.Name := ' LNameHC ' + x.ToString;
LNameHC.Align := TAlignLayout.Client;
LNameHC.Margins.Left := 2;
LNameHC.AutoSize := True;
LNameHC.TextSettings.FontColor := $FF000000;
LNameHC.TextSettings.Font.Size := 10;
LNameHC.StyledSettings := [];
LNameHC.Text := NameP;
LNameHC.Parent := PanelHC;
PanelHC1 := TPanel.Create(Self);
PanelHC1.Name := 'PanelHC1' + x.ToString;
PanelHC1.Align := TAlignLayout.Left;
PanelHC1.Width := 26;
PanelHC1.Parent := LayoutHC;
BotonHC := TButton.Create(Self);
BotonHC.Name := 'BotonHC' + x.ToString;
BotonHC.Align := TAlignLayout.Client;
BotonHC.TextSettings.Font.Style := [TFontStyle.fsBold];
BotonHC.Text := '>';
BotonHC.OnClick := ClickHistorialC;
BotonHC.Parent := PanelHC1;
PanelHC2 := TPanel.Create(Self);
PanelHC2.Name := 'PanelHC2' + x.ToString;
PanelHC2.Align := TAlignLayout.Client;
PanelHC2.Parent := LayoutHC;
HorzScrollBoxHC := THorzScrollBox.Create(Self);
HorzScrollBoxHC.Name := 'HorzScrollBoxHC' + x.ToString;
HorzScrollBoxHC.Align := TAlignLayout.Client;
HorzScrollBoxHC.ShowScrollBars := False;
HorzScrollBoxHC.Parent := PanelHC2;
RectHC_R1 := TRectangle.Create(Self);
RectHC_R1.Name := 'RectHC_R1' + x.ToString;
RectHC_R1.Align := TAlignLayout.Left;
RectHC_R1.Fill.Color := $FF1E90FF;
RectHC_R1.Margins.Bottom := 2;
RectHC_R1.Margins.Left := 2;
RectHC_R1.Margins.Top := 2;
RectHC_R1.Sides := [];
RectHC_R1.Stroke.Kind := TBrushKind.None;
RectHC_R1.Width := 23;
RectHC_R1.XRadius := 4;
RectHC_R1.YRadius := 4;
RectHC_R1.Parent := HorzScrollBoxHC;
LabelHC_R1 := TLabel.Create(Self);
LabelHC_R1.Name := ' LabelHC_R1' + x.ToString;
LabelHC_R1.Align := TAlignLayout.Client;
LabelHC_R1.AutoSize := True;
LabelHC_R1.TextSettings.FontColor := $FFFFFFFF;
LabelHC_R1.TextSettings.Font.Size := 11;
LabelHC_R1.TextSettings.HorzAlign := TTextAlign.Center;
LabelHC_R1.StyledSettings := [];
LabelHC_R1.Text := R1.ToString;
LabelHC_R1.Parent := RectHC_R1;
{ ………………….
Up to 8 TRectangles and TLabels to create here…
……………………. }
RectHC_R10 := TRectangle.Create(Self);
RectHC_R10.Name := 'RectHC_R10' + x.ToString;
RectHC_R10.Align := TAlignLayout.Left;
RectHC_R10.Fill.Color := $FF1E90FF;
RectHC_R10.Margins.Bottom := 2;
RectHC_R10.Margins.Left := 2;
RectHC_R10.Margins.Top := 2;
RectHC_R10.Sides := [];
RectHC_R10.Stroke.Kind := TBrushKind.None;
RectHC_R10.Width := 23;
RectHC_R10.XRadius := 4;
RectHC_R10.YRadius := 4;
RectHC_R10.Parent := HorzScrollBoxHC;
LabelHC_R10 := TLabel.Create(Self);
LabelHC_R10.Name := ' LabelHC_R10' + x.ToString;
LabelHC_R10.Align := TAlignLayout.Client;
LabelHC_R10.AutoSize := True;
LabelHC_R10.TextSettings.FontColor := $FFFFFFFF;
LabelHC_R10.TextSettings.Font.Size := 11;
LabelHC_R10.TextSettings.HorzAlign := TTextAlign.Center;
LabelHC_R10.StyledSettings := [];
LabelHC_R10.Text := R10.ToString;
LabelHC_R10.Parent := RectHC_R1;
end;
Upvotes: 0
Views: 390
Reputation: 4730
You will never get acceptable speed with that many controls, especially on a mobile device.
For rectangles, text, lines, ... I'd simply use custom painting. You could use a PaintBox with an OnPaint
event.
procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
begin
Canvas.Fill.Color := $FF1E90FF;
Canvas.FillRect(RectF(10, 10, 200, 50), 4, 4, [], 1.0);
Canvas.Fill.Color := $FFFFFFFF;
Canvas.Font.Size := 13.0;
Canvas.FillText(RectF(10, 10, 200, 50), 'My Text', True, 1.0, [], TTextAlign.Center, TTextAlign.Center);
end;
This event will be called whenever a screen update is needed. If your data has changed and you want to update the screen, call PaintBox1.InvalidateRect({...area that needs to be updated});
. This will trigger a screen update.
A button is a bit more tricky, you'd have to use the OnMouseDown and OnMouseUp events and manually evaluate the mouse clicks.
In the long run, it will probably make sense to have your own control that derives from TControl
or TStyledControl
that paints in an overridden Paint
method.
Upvotes: 1