在运行时创建大量控件以最小化firemonkey中的加载时间的最佳方法是什么?

时间:2015-04-08 16:22:20

标签: android delphi runtime controls firemonkey

我在使用JSON XSuperObject的Firemonkey和从Web API检索的数据的Delphi XE7中的Android应用程序中遇到性能速度问题。

我的场景是一个系统排名表,在每次迭代时在运行时创建29个控件,有时候玩家的数量应该超过90个,所以对于每次迭代(90 * 27),它在运行时创建2610个控件。 在Windows平台上测试花了3秒钟,但在Android的移动平台上花了17秒。我知道它会影响应用程序的性能,但我不知道Windows和Android的加载时间的显着差异。

那么有没有办法减少加载时间或优化下面的代码以获得最佳性能?谢谢。

亲切的问候。

{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;

1 个答案:

答案 0 :(得分:0)

使用那么多控件永远无法获得可接受的速度,尤其是在移动设备上。

对于矩形,文字,线条......我只是使用自定义绘画。您可以使用带有OnPaint事件的PaintBox。

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;

只要需要更新屏幕,就会调用此事件。如果您的数据已更改并且您想要更新屏幕,请致电PaintBox1.InvalidateRect({...area that needs to be updated});。这将触发屏幕更新。

按钮有点棘手,您必须使用OnMouseDown和OnMouseUp事件并手动评估鼠标点击次数。

从长远来看,拥有自己的控件可能是有意义的,该控件源自TControlTStyledControl,它使用重写的Paint方法进行绘制。