Code running in reverse on Android

I have been attempting to update a CombBox's items from an XML file. The code below works fine in Windows yet fails on Android. I have included the XML file in the deployment manager and set the remote path to ./assets/internal. Below is the code used as well as the XML file. 

Attempting to debug I added a few messages in the code block. To my surprise they were running in reverse on android. I created another multi device app with just a button. In the onclick event I simply added two Showmessages...

procedure TForm1.Button1Click(Sender: TObject);
begin
  Showmessage('One');
  Showmessage('Two');
end;

On Windows platform I get what I expect. First message is 'One' the next is 'Two'. However, on Android the first message is 'Two' followed by 'One'. I have restarted the IDE as well as rebooted yet the problem remains. I am assuming this is where my problem lies with the XML code below? What am I missing. Any ideas?

Code block. Form has a TXMLDocument, Button, and ComboBox component.

procedure TForm2.Button1Click(Sender: TObject);
var
  i: Integer;
  XMLpath: String;
begin
  XMLPath := TPath.Combine(TPath.GetDocumentsPath, 'fertilizers.xml');

  if FileExists(XMLPath) then
    begin
      Showmessage('The XML file exists in directory ' + XMLPath);
      XMLDocument1.FileName := XMLPath;
      XMLDocument1.Active := True;
      ComboBox1.Clear;
    end else

    begin
      Showmessage('The XML file does not exist! Exiting...');
      Exit;
    end;

  {Populate ComboBox1 with fertilizer names}
  if XMLDocument1.DocumentElement.ChildNodes.Count <> null then
    begin
      for i:=0 to XMLDocument1.DocumentElement.ChildNodes.Count-1 do
        begin
          ComboBox1.Items.Add(XMLDocument1.DocumentElement.ChildNodes[i].Attributes['fertname']);
          ComboBox1.ItemIndex := 0;
        end;

    end else
      Showmessage('There are no XMLDocumentElements to be processed');
end;

Here is the structure of the XML file.

3480.fertilizers.xml
<DryFertilizers>
     <fert fertname="KNO3">
         <elem name="NO3">0.6133</elem>
         <elem name="N">0.138539</elem>
         <elem name="K">0.386716</elem>
         <elem name="tsp">5200</elem>
         <elem name="sol">360</elem>
         <elem name="target"> "NO3"</elem>
     </fert>

     <fert fertname="KH2PO4">
         <elem name="PO4"> "0.6979"</elem>
         <elem name="P"> "0.227605"</elem>
         <elem name="K"> "0.2873"</elem>
         <elem name="tsp"> "5600"</elem>
         <elem name="sol"> "220"</elem>
         <elem name="target"> "PO4"</elem>
     </fert>
</DryFertilizers>

  • The code below works fine in Windows yet fails on Android.

    In what way exactly does it fail?  Please elaborate.  The only thing I see wrong with your code is this line:

    if XMLDocument1.DocumentElement.ChildNodes.Count <> null then

    The 'Count' is an 'Integer', but 'null' is a 'Variant'.  You should be comparing with 0 instead:

    if XMLDocument1.DocumentElement.ChildNodes.Count <> 0 then

    That said, I would suggest a few tweaks to your code to clean it up:

    procedure TForm2.Button1Click(Sender: TObject);
    var
      XMLPath: String;
      DocElement: IXMLElement;
      i, cnt: Integer;
    begin
      ComboBox1.Clear;
    
      XMLPath := TPath.Combine(TPath.GetDocumentsPath, 'fertilizers.xml');
      if not FileExists(XMLPath) then
      begin
        ShowMessage('The XML file does not exist! Exiting...');
        Exit;
      end;
    
      //ShowMessage('The XML file exists in path ' + XMLPath);
      XMLDocument1.FileName := XMLPath;
      XMLDocument1.Active := True;
    
      {Populate ComboBox1 with fertilizer names}
      DocElement := XMLDocument1.DocumentElement;
      cnt := DocElement.ChildNodes.Count;
      if cnt = 0 then
      begin
        ShowMessage('There are no XML Elements to be processed');
        Exit;
      end;
    
      for i := 0 to cnt-1 do begin
        ComboBox1.Items.Add(DocElement.ChildNodes[i].Attributes['fertname']);
      end;
    
      ComboBox1.ItemIndex := 0;
    end;

    On Windows platform I get what I expect. First message is 'One' the next is 'Two'. However, on Android the first message is 'Two' followed by 'One'.

    ShowMessage() runs *synchronously* on Windows, but *asynchronously* on Android.  This is documented behaviorAndroid does not support modal dialogs.  You are simply seeing the 2nd popup window being displayed on top of the 1st popup window.

  • Thank you Remy! I had no idea Showmessage ran asynchronously on Android. The error I was seeing was the, Showmessage('The XML file does not exist! Exiting...');. 

    After you said you saw nothing wrong with the code I ignored debugging at that level. Instead, I simply deleted the XML file in the deployment page and added it again. It now works perfectly. Not sure what the problem was there. 

    Btw, I do like you code much better. Thank you. Also, I never saw the null versus 0 . Amazing how I can see something a hundred times and never actually SEE it lol. Thanks again!

  • The error I was seeing was the, Showmessage('The XML file does not exist! Exiting...');. 

    I don't trust FileExists(), it is known to sometimes return incorrect results, not to mention it introduces a race condition (the file could be moved/deleted after the check is done and before the file is opened).  I try not to use it whenever possible.  It would be more straight forward to just activate the XMLDocument unconditionally and catch any error it may raise, eg:

    procedure TForm2.Button1Click(Sender: TObject);
    var
      XMLPath: String;
      ...
    begin
      ...
    
      XMLPath := TPath.Combine(TPath.GetDocumentsPath, 'fertilizers.xml');
    
      try
        XMLDocument1.FileName := XMLPath;
        XMLDocument1.Active := True;
      except
        on E: Exception do
        begin
          ShowMessage('The XML file could not be opened! Exiting...' + sLineBreak + sLineBreak + E.Message);
          Exit;
        end;
      end;
    
      //ShowMessage('The XML file exists in path ' + XMLPath);
    
      ...
    end;