Delphi 随着列数的增加,TTeeGrid在运行时的创建速度会变慢

Delphi 随着列数的增加,TTeeGrid在运行时的创建速度会变慢,delphi,dynamic,firemonkey,tdataset,tgrid,Delphi,Dynamic,Firemonkey,Tdataset,Tgrid,我正在API提供的运行时创建TTegrid(TDataSet子体)。我注意到,随着列数的增加,性能会下降。也就是说,创建TTeeGrid的时间越来越慢 我在这里开发firemonkey应用程序,当它达到20列或更多列时,在iOS和Android中的性能是显而易见的 这是我的密码: procedure TformMain.btnCreateTeeGridClick(Sender: TObject); begin FreeAndNil(CanvassGrid); // delete the o

我正在API提供的运行时创建TTegrid(TDataSet子体)。我注意到,随着列数的增加,性能会下降。也就是说,创建TTeeGrid的时间越来越慢

我在这里开发firemonkey应用程序,当它达到20列或更多列时,在iOS和Android中的性能是显而易见的

这是我的密码:

procedure TformMain.btnCreateTeeGridClick(Sender: TObject);
begin
   FreeAndNil(CanvassGrid); // delete the old grid

   // create a new grid
   CanvassGrid := TTeeGrid.Create(recCanvass);
    With CanvassGrid do
    begin
      Parent := recCanvass;
      Align := TAlignLayout.Client;
      Margins.Top := 5;
      Margins.Left := 5;
      Margins.Right := 5;
      Margins.Bottom := 5;
      ScrollBars.Visible := True;
      Header.Format.Font.Size := 11;
      Cells.Format.Font.Size := 11;
      TabOrder := 0;
      ScrollBars.Visible := False;
    end;
end;
是否有一种方法可以提高性能,或者我的代码中是否遗漏了导致性能降低的内容


更新1:最小可复制示例

FMX文件

object Form9: TForm9
  Left = 0
  Top = 0
  Caption = 'MRE TeeGrid Runtime'#13#10
  ClientHeight = 480
  ClientWidth = 294
  FormFactor.Width = 320
  FormFactor.Height = 480
  FormFactor.Devices = [Desktop]
  DesignerMasterStyle = 0
  object btn1: TButton
    Align = Bottom
    Position.Y = 440.000000000000000000
    Size.Width = 294.000000000000000000
    Size.Height = 40.000000000000000000
    Size.PlatformDefault = False
    TabOrder = 9
    Text = 'CREATE TEEGRID'
    OnClick = btn1Click
  end
  object aniSearchProcess: TAniIndicator
    Position.X = 128.000000000000000000
    Position.Y = 216.000000000000000000
  end
  object lyt1: TLayout
    Align = Client
    Size.Width = 294.000000000000000000
    Size.Height = 440.000000000000000000
    Size.PlatformDefault = False
    TabOrder = 11
  end
  object cur1: TFDGUIxWaitCursor
    Provider = 'FMX'
    Left = 32
    Top = 32
  end
  object dvr1: TFDPhysSQLiteDriverLink
    Left = 88
    Top = 32
  end
  object con1: TFDConnection
    Params.Strings = (
      'DriverID=SQLite')
    Connected = True
    LoginPrompt = False
    Left = 144
    Top = 32
  end
  object loc1: TFDLocalSQL
    Connection = con1
    Active = True
    Left = 200
    Top = 32
  end
  object rsc1: TRESTClient
    Accept = 'application/json, text/plain; q=0.9, text/html;q=0.8,'
    AcceptCharset = 'utf-8, *;q=0.8'
    BaseURL = 
      'https://me6hwinr2k.execute-api.ap-southeast-1.amazonaws.com/v0/d' +
      'bqueries?item-var=9&qty=25'
    Params = <>
    Left = 32
    Top = 112
  end
  object rsq1: TRESTRequest
    Client = rsc1
    Params = <>
    Response = rsp1
    SynchronizedEvents = False
    Left = 32
    Top = 176
  end
  object rsp1: TRESTResponse
    ContentType = 'application/json'
    Left = 32
    Top = 240
  end
  object rsd1: TRESTResponseDataSetAdapter
    Active = True
    Dataset = mtb1
    FieldDefs = <>
    Response = rsp1
    Left = 32
    Top = 304
  end
  object mtb1: TFDMemTable
    Active = True
    FieldDefs = <
      item
        Name = 'Category'
        DataType = ftWideString
        Size = 255
      end
      item
        Name = 'ID'
        DataType = ftWideString
        Size = 255
      end
      item
        Name = 'Item'
        DataType = ftWideString
        Size = 255
      end
      item
        Name = 'Qty'
        DataType = ftWideString
        Size = 255
      end
      item
        Name = 'Container'
        DataType = ftWideString
        Size = 255
      end
      item
        Name = 'Size'
        DataType = ftWideString
        Size = 255
      end
      item
        Name = 'Ex temporibus dolore consequatur.'
        DataType = ftWideString
        Size = 255
      end
      item
        Name = 'Et cum aut est nostrum...'
        DataType = ftWideString
        Size = 255
      end
      item
        Name = 'Sequi quibusdam eum.'
        DataType = ftWideString
        Size = 255
      end>
    IndexDefs = <>
    FetchOptions.AssignedValues = [evMode]
    FetchOptions.Mode = fmAll
    ResourceOptions.AssignedValues = [rvSilentMode]
    ResourceOptions.SilentMode = True
    UpdateOptions.AssignedValues = [uvCheckRequired, uvAutoCommitUpdates]
    UpdateOptions.CheckRequired = False
    UpdateOptions.AutoCommitUpdates = True
    StoreDefs = True
    Left = 32
    Top = 368
  end
end

这是Steema针对VCL/FMX的TeeGrid还是其他什么?无论如何,任何网格样式的组件都不太可能是TDataSet的后代,TDataSet是一种非可视数据访问组件。更常见的情况是,网格有一个属性,允许它连接到TDataSource,然后引用TDataSet子体?请提供一个。@MartynA我在这里并没有实际使用LiveBindings,而是在运行时直接连接到FDMemTable作为源数据和结构。我已按要求提供了MRE(见上文更新1)。请注意,提供的示例API仅限于演示目的。在这里,当我运行您的示例时,所有时间都用于建立安全连接以获取内容。只要连接在当前运行时并没有超时,额外按下按钮可以快速创建网格。可能有助于一些列数较大的用户使用
try columns.beginupdate围绕列设置
最后是columns.endupdate@Brian谢谢你的建议。我尝试了你的建议,但它有所改善,但当我达到35列或更多时,它又开始减速。我怀疑是这些列的开销数据使其随着列数的增加而变慢。这是Steema针对VCL/FMX的TeeGrid还是其他什么?无论如何,任何网格样式的组件都不太可能是TDataSet的后代,TDataSet是一种非可视数据访问组件。更常见的情况是,网格有一个属性,允许它连接到TDataSource,然后引用TDataSet子体?请提供一个。@MartynA我在这里并没有实际使用LiveBindings,而是在运行时直接连接到FDMemTable作为源数据和结构。我已按要求提供了MRE(见上文更新1)。请注意,提供的示例API仅限于演示目的。在这里,当我运行您的示例时,所有时间都用于建立安全连接以获取内容。只要连接在当前运行时并没有超时,额外按下按钮可以快速创建网格。可能有助于一些列数较大的用户使用
try columns.beginupdate围绕列设置
最后是columns.endupdate@Brian谢谢你的建议。我尝试了你的建议,但它有所改善,但当我达到35列或更多时,它又开始减速。我怀疑是列的开销数据使得它随着列的增加而变慢。
unit Main;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
  FireDAC.UI.Intf, FireDAC.FMXUI.Wait, FireDAC.Stan.ExprFuncs,
  FireDAC.Phys.SQLiteDef, FireDAC.Stan.Intf, FireDAC.Stan.Option,
  FireDAC.Stan.Error, FireDAC.Phys.Intf, FireDAC.Stan.Def, FireDAC.Stan.Pool,
  FireDAC.Stan.Async, FireDAC.Phys, FireDAC.Phys.SQLite, Data.DB,
  FireDAC.Stan.Param, FireDAC.DatS, FireDAC.DApt.Intf, REST.Types,
  FMX.Controls.Presentation, FMX.StdCtrls, FireDAC.Comp.DataSet,
  FireDAC.Comp.Client, REST.Response.Adapter, REST.Client, Data.Bind.Components,
  Data.Bind.ObjectScope, FireDAC.Phys.SQLiteVDataSet, FireDAC.Comp.UI,
  FMXTee.Control, FMXTee.Grid, FMX.Layouts;

type
  TForm9 = class(TForm)
    cur1: TFDGUIxWaitCursor;
    dvr1: TFDPhysSQLiteDriverLink;
    con1: TFDConnection;
    loc1: TFDLocalSQL;
    rsc1: TRESTClient;
    rsq1: TRESTRequest;
    rsp1: TRESTResponse;
    rsd1: TRESTResponseDataSetAdapter;
    mtb1: TFDMemTable;
    btn1: TButton;
    aniSearchProcess: TAniIndicator;
    lyt1: TLayout;
    procedure btn1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form9: TForm9;
  tgd1: TTeeGrid;

implementation

{$R *.fmx}

procedure TForm9.btn1Click(Sender: TObject);
var
  i, CanvassItemId, e : Integer;
begin
  aniSearchProcess.Visible := True;
  aniSearchProcess.Enabled := True;
  {$IFDEF MSWINDOWS}
    Application.ProcessMessages;
  {$ENDIF}
  {$IF DEFINED(iOS) or DEFINED(ANDROID)}
    Application.HandleMessage;
  {$ENDIF}

  FreeAndNil(tgd1); //free old grid

  //create new grid
  tgd1 := TTeeGrid.Create(lyt1);
  With tgd1 do
  begin
    Parent := lyt1;
    Align := TAlignLayout.Client;
    Margins.Top := 5;
    Margins.Left := 5;
    Margins.Right := 5;
    Margins.Bottom := 5;
    ScrollBars.Visible := True;
    Header.Format.Font.Size := 11;
    Cells.Format.Font.Size := 11;
    TabOrder := 0;
    ScrollBars.Visible := False;
  end;

  con1.StartTransaction;
  try
    //define the API here for duplicate/update, initial click and subsequent clicks
    rsc1.BaseURL := ...;
    rsq1.Execute;
    rsd1.Active := True;
    mtb1.Active;
    tgd1.DataSource := mtb1;
    tgd1.Enabled := True;

    // adjust the column properties dynamically
    with tgd1 do
    begin
      for i := 0 to Columns.Count -1 do
      begin
        if i = 0 then
        begin
          Columns[i].Visible := False; // category column
        end
        else if (i = 1) then
        begin
          Columns[i].Visible := False; // id column
        end
        else if (i = 2) then
        begin
          Columns[i].Width.Value := 120; // item column
        end
        else if (i = 3) then
        begin
          Columns[i].Width.Value := 30; // qty column
        end
        else if (i = 4) then
        begin
          Columns[i].Width.Value := 50; // container column
        end
        else if (i = 5) then
        begin
          Columns[i].Width.Value := 50; // size column
        end
        else
        begin
          Columns[i].Width.Value := 50; // subsequent random columns
        end;
      end;
    end;
  finally
    con1.Commit;
  end;

  aniSearchProcess.Visible := False;
  aniSearchProcess.Enabled := False;
  {$IFDEF MSWINDOWS}
    Application.ProcessMessages;
  {$ENDIF}
  {$IF DEFINED(iOS) or DEFINED(ANDROID)}
    Application.HandleMessage;
  {$ENDIF}

end;

end.