我在 API 提供的运行时创建 TTeeGrid(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
FMX 程序
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.