JakeSays
JakeSays

Reputation: 2068

Correctly using TAniIndicator in firemonkey mobile dev for wait for processing

I am using Delphi XE-5 (Firemonkey Mobile Application)

I am trying to get the TAniIndicator to work, by displaying during my long processing. I have a TAniIndicator (AniIndi) on my main form, but it does not spin. It displays correctly, but does not spin.

begin
 Loading:= True;
 AniIndi.Visible:= True;
 AniIndi.Enabled:= True;
 UpdateAll;
 Application.ProcessMessages;

 //do my processsing here

 Loading:= False;
 AniIndi.Enabled:= False;
 AniIndi.Visible:= False;
 UpdateAll;
 Application.ProcessMessages;
end;

//EDIT BASED ON REMY's ANSWER

TLoadThread = class(TThread)
 public
  Config: Boolean;
  constructor Create(const aConfig: Boolean); reintroduce;
 protected
  procedure DoProcessing;
  procedure Execute; Override;
 end;

var
 loading: Boolean = false;
 zLThread: TLoadThread = nil;

constructor TLoadThread.Create(const aConfig: Boolean);
begin
 inherited Create(true);
 Config:= aConfig;
end;

procedure TLoadThread.DoProcessing;
var
begin
 //do processing here and update main form
end;

procedure TLoadThread.Execute;
begin
 FreeOnTerminate:= true;
 Synchronize(DoProcessing);
end;


procedure TfrmMain.FormActivate(Sender: TObject);
begin
 zLThread:= TLoadThread.Create(True, Host, NamePath, Config, Port);
 zLThread.OnTerminate := ThreadTerminated;
 zLThread.Start;
 Loading := True;
 AniIndi.Visible := True;
 AniIndi.Enabled := True;
 UpdateAll;
end;

procedure TfrmMain.ThreadTerminated(Sender: TObject);
begin
  zLThread := nil;
  Loading := False;
  AniIndi.Enabled := False;
  AniIndi.Visible := False;
  UpdateAll;
end;

Upvotes: 5

Views: 19790

Answers (2)

David Drouin
David Drouin

Reputation: 29

The problem come from the timer Inside the TAnimation, by chance Embarcadero add a global variable.

Add the following code in your FormCreate procedure

{$IFDEF IOS}
AniFrameRate := 10;
{$ENDIF}

Upvotes: 2

Remy Lebeau
Remy Lebeau

Reputation: 596121

Your main thread needs to stay responsive to the message queue while your long process is running. If not, you are blocking the animation (and other aspects of the UI) from receiving new messages, like paint requests and timers notifies. You need to move any long processing to a separate thread instead. Start the thread and then start the animation. Let the main thread handle the UI normally in the meantime. When the thread is finished, have it notify the main thread, which can then stop the animation, and finish any other processing it needs on the result of the thread, if any. For example:

type
  TLoadThread = class(TThread)
  public
    Host: string;
    NamePath: string;
    Port: Integer;
    Config: Boolean;
    constructor Create(const aHost, aNamePath: string; aPort: Integer; aConfig: Boolean); reintroduce;
  protected
    procedure Execute; override;
  end;

constructor TLoadThread.Create(const aHost, aNamePath: string; aPort: Integer; aConfig: Boolean);
begin
  inherited Create(True);
  FreeOnTerminate := True;
  Host := aHost;
  NamePath := aNamePath;
  Port := aPort;
  Config := aConfig;
end;

procedure TLoadThread.Execute;
begin
  //do processing

  Synchronize(
    procedure
      //update main form
    end
  );

  //do processing
end;

var
  Loading: Boolean = False;
  zLThread: TLoadThread = nil;

procedure TfrmMain.FormActivate(Sender: TObject);
begin
  zLThread := TLoadThread.Create(Host, NamePath, Port, Config);
  zLThread.OnTerminate := ThreadTerminated;
  zLThread.Start;
  Loading := True;
  AniIndi.Visible := True;
  AniIndi.Enabled := True;
  UpdateAll;
end;

procedure TfrmMain.ThreadTerminated(Sender: TObject);
begin
  zLThread := nil;
  Loading := False;
  AniIndi.Enabled := False;
  AniIndi.Visible := False;
  UpdateAll;
end;

Upvotes: 14

Related Questions