DelphiのAndroidアプリケーションでJavaのスレッドを実行する

Delphi XE6のモバイルアプリケーションを使って、AndroidアプリケーションのJavaのスレッドを実行してみます。

AndroidのSDKが提供しているクラスには、Runnableインターフェースを引数に受け取るメソッドがあります。
そのようなメソッドをできるだけ手軽に使いたい。

Runnableインターフェースを継承したJavaのクラスを作成して、作成したJavaのクラスからDelphiのコードを呼び出す方法もありますが、ちょっと手間がかかります。
できれば、Delphiだけで完結したい。

そこで、今回紹介する方法になります。

Runnableインターフェースを継承したDelphiのクラスを作成します。
このクラスはコンストラクタの引数にスレッドで実行する処理をとります。

type
  TRunner = class(TJavaLocal, JRunnable)
  private
    FProc: TThreadProcedure;
  public
    constructor Create(Proc: TThreadProcedure); overload;
    procedure run; cdecl;
  end;

implementation

constructor TRunner.Create(Proc: TThreadProcedure);
begin
  inherited Create;
  FProc := Proc;
end;

procedure TRunner.run;
begin
  FProc;
end;

TThreadProcedure型はSystem.Classesユニットで次のように定義されています。

  TThreadProcedure = reference to procedure;

このクラスをAndroidアプリケーションで使ってみます。

begin
  SharedActivity.runOnUiThread(TRunner.Create(
    procedure
    begin
      Log.d('TRunner.run!');
    end));
end;

コンパイルはできますが、実行するとエラーが発生してアプリケーションが強制終了してしまいます。

原因は、スレットが開始する前にTRunnerオブジェクトが破棄されてしまうためです。

TRunnerオブジェクトが自動的に解放されないように、変数に保持するようにしてみます。

type
  TRunner = class(TJavaLocal, JRunnable)
  private
    // ↓追加
    class var JRunnables: System.Generics.Collections.TThreadList<JRunnable>;
    class constructor Create;
    class destructor Destroy;

クラスが読み込まれたされたときにクラス変数JRunnablesを生成し、クラスが破棄されたときにクラス変数JRunnablesを破棄します。

implementation

class constructor TRunner.Create;
begin
  JRunnables := TThreadList<JRunnable>.Create;
end;

class destructor TRunner.Destroy;
begin
  JRunnables.DisposeOf;
end;

TRunnerクラスのインスタンスが生成されたときに、JRunnables変数に登録します。

constructor TRunner.Create(Proc: TThreadProcedure);
begin
  inherited Create;
  FProc := Proc;
  JRunnables.Add(Self);
end;

スレッドの処理が終了したら、JRunnables変数から削除します。

procedure TRunner.run;
begin
  try
    FProc;
  finally
    JRunnables.Remove(Self);
  end;
end;

アプリケーションを実行します。

  SharedActivity.runOnUiThread(TRunner.Create(
    procedure
    begin
      Log.d('TRunner.run!');
    end));

今度は正しく動作しました。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください