【问题标题】:How to extract original JString value from Listbox in Android Kitkat Delphi XE8如何从 Android Kitkat Delphi XE8 中的 Listbox 中提取原始 JString 值
【发布时间】:2016-01-04 07:20:14
【问题描述】:

我正在使用 Delphi xe8 制作一个测试 android 多设备应用程序。我将对象附加到列表框中的项目,如下所示:

 unit Unit1;

 interface

 uses
  System.SysUtils, System.Types, System.UITypes, System.Classes,  
   System.Variants,

  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics,    
  Androidapi.JNI.JavaTypes, FMX.Dialogs,
 FMX.Controls.Presentation, FMX.StdCtrls, FMX.Layouts, FMX.ListBox,    
 Androidapi.Helpers;

 type
   TForm1 = class(TForm)
   ListBox1: TListBox;
   Button1: TButton;
   Button2: TButton;
   procedure Button1Click(Sender: TObject);
   procedure Button2Click(Sender: TObject);
   private
   { Private declarations }
   public
   { Public declarations }
   end;

     var
    Form1: TForm1;

    implementation
    {$R *.fmx}

    //this where I am Attaching objects to items
    procedure TForm1.Button1Click(Sender: TObject);
    var
    str:string;
    jstr1:JString;
    begin
    str:='apple';
    jstr1:=StringToJString(str);
    ListBox1.Items.AddObject('fruit', TObject(jstr1));
    end;


    //this where I am extracting the jstring objects
    procedure TForm1.Button2Click(Sender: TObject);
     var
    jstr2:JString;
    str2:string;
    begin
    jstr2:=JString(ListBox1.Items.Objects[i]);
    str2:=JStringToString(jstr2);
    showmessage('the fruit of the day is '+str2);
    end;

   end.

上面的代码运行正常,并且 jstring 对象附加到项目,但是,当我想提取已附加到项目的 jstring 对象时,我这样做:

 jstr2:=JString(ListBox1.Items.Objects[i]);
 //Above give me an AV: I get incompatible types TObject and JString

 str2:=JStringToString(jstr2);

由于类型 TObject 和 JString 不兼容,上述代码无法编译。但是,如果附加了一个字符串作为对象(而不是一个 jstring)并且想要取回那些我可以做的字符串对象:

str2:=String(ListBox1.Items.Objects[i]);

这适用于常规字符串。我该如何解决这个问题,附加和提取jstring?

【问题讨论】:

  • FWIW,AV 是访问冲突,意味着您正在访问不属于程序的内存,在运行时。我猜你的意思是编译期间出现编译器错误?
  • 您的错误消息意味着 JString 不是 TObject 后代。您也许可以存储 JString 的地址,但我不熟悉 JString 究竟是什么,所以我不愿意肯定地说。

标签: android delphi listbox android-4.4-kitkat delphi-xe8


【解决方案1】:

这只是一个建议,我无法检查这个(这里没有安装),但你可以编写一个简单的对象类型并将其存储(我把它放在它自己的单元中,然后你在你的表单单元中使用它) :

unit StringObjs;

interface

uses 
  Androidapi.JNI.JavaTypes;

type
  TStringObj = class
  private
    FPayload: string;
  public
    constructor Create(const Payload: JString);
    class operator Explicit(const Obj: TStringObj): string;
  end;

implementation

uses
  Androidapi.Helpers;

constructor TStringObj.Create(const Payload: JString);
begin
  FPayload := JStringToString(Payload); // store string, not JString!
end;

class operator TStringObj.Explicit(const Obj: TStringObj): string;
begin
  Result := Obj.FPlayload;
end;

end.

然后在表单单元的实现部分中使用它,例如:

implementation

uses ..., StringObjs;

...

  ListBox1.Items.AddObject('fruit', TStringObj.Create(jstr1));

反过来:

  MyString := string(ListBox1.Items[0] as TStringObj);

请注意,表单只是一个类,但 IDE 知道并可以使用表单设计器进行编辑。要声明其他类,请执行与上面类似的操作。阅读Delphi Language Guide 了解更多信息。

【讨论】:

  • 我将类型放在它自己的单元中并编辑了我的答案。您应该真正了解类以及如何声明和使用它们。请参阅我的答案中的链接。
  • “创建”声明与之前的声明不同。我相信这是'const'缺少第一个声明(接口部分中的那个)的原因。我也为此添加了 const 以测试它是否可以工作,但这导致了我之前提到的错误“未声明的 FPayload”。
  • 已编辑:在 Create 的声明中添加了一个 const。你可以试着理解代码,然后自己解决。
  • 非常感谢 Rudy Velthuis。我也遵循了您关于阅读“Delphi 语言指南”的建议。我从没想过在这里被勺子喂食,但我很高兴有一个解决方案。我将尝试编辑/更新帖子以包含完整的问题和解决方案,供其他新手使用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-13
  • 2015-10-06
  • 2023-03-13
  • 1970-01-01
相关资源
最近更新 更多