While other possibilities are there, I'll assume LAMW is being used here since the original post mentioned jTextView. If you followed my first reply, you'll see the thread is working but can not call Synchronize.
To prove that Synchronize works, simply add a jTimer to your main form and have it call CheckSynchronize(). If you are satisfied with this timer, good for you.
A call to Synchronize uses WakeMainThread. Which makes finding a way to call CheckSynchronize on the main thread simple. Android provides RunOnUiThread. Unfortunately the implementation in LAMW is not correct. It uses PJNIEnv of the main thread instead of the calling thread. A thread var can be filled by each thread. Along these lines:
threadvar
env:PJNIEnv;//<--- has to be a threadvar
procedure TWorkerThread.Execute;
begin
gVM^.AttachCurrentThread(gVM,@env,nil);//<--- needed for every thread
WakeMainThread:=LetsWakeMainThread;//<--- needed once
x:=0;
repeat
inc(x);
Synchronize(UpdateValue);
Sleep(1000);
until Terminated;
gVM^.DetachCurrentThread(gVM);//<--- when you are done with the thread (Free/Destroy)
end;
LetsWakeMainThread is:
procedure TWorkerThread.LetsWakeMainThread(Sender:TObject);
begin
//MainForm.RunOnUiThread(Integer(Self));//<--- Wrong env variable, not for this thread
TAndroidModule1(MainForm).RunOnUiThread_corrected(env,0);
end;
RunOnUiThread_corrected is:
procedure TAndroidModule1.RunOnUiThread_corrected(correct_env:PJNIEnv;_tag: integer);
begin
//in designing component state: set value here...
if Initialized then
jni_proc_i(correct_env, jSelf, 'RunOnUiThread', _tag);
end;
And the most important part is to add CheckSynchronize() to the OnRunOnUiThread event of the main form:
procedure TAndroidModule1.AndroidModule1RunOnUiThread(Sender:TObject;tag:integer);
begin
CheckSynchronize();
end;
Full code of the thread:
unit uThreadTest;
{$mode delphi}
interface
uses
Classes, SysUtils,
AndroidWidget,And_jni;
type
{ TWorkerThread }
TWorkerThread=class(TThread)
private
procedure UpdateValue;
protected
procedure Execute; override;
public
MainForm:jForm;
x:integer;
OnUpdate:Procedure of object;
procedure LetsWakeMainThread(Sender: TObject);
end;
implementation
uses
unit1;
{ TWorkerThread }
procedure TWorkerThread.UpdateValue;
begin
if Assigned(OnUpdate) then
OnUpdate;
end;
threadvar
env:PJNIEnv;//<--- has to be a threadvar
procedure TWorkerThread.Execute;
begin
gVM^.AttachCurrentThread(gVM,@env,nil);//<--- needed for every thread
WakeMainThread:=LetsWakeMainThread;//<--- needed once
x:=0;
repeat
inc(x);
Synchronize(UpdateValue);
Sleep(1000);
until Terminated;
gVM^.DetachCurrentThread(gVM);//<--- when you are done with the thread (Free/Destroy)
end;
procedure TWorkerThread.LetsWakeMainThread(Sender:TObject);
begin
//MainForm.RunOnUiThread(Integer(Self));//<--- Wrong env variable, not for this thread
TAndroidModule1(MainForm).RunOnUiThread_corrected(env,0);
end;
end.
Main form relevant code:
procedure TAndroidModule1.LetsUpdate;
begin
jTextView1.Text:=WorkerThread.x.ToString;
end;
procedure TAndroidModule1.RunOnUiThread_corrected(correct_env:PJNIEnv;_tag: integer);
begin
if Initialized then
jni_proc_i(correct_env, jSelf, 'RunOnUiThread', _tag);
end;
procedure TAndroidModule1.StartBtnClick(Sender:TObject);
begin
if WorkerThread=nil then
begin
WorkerThread:=TWorkerThread.Create(True);
WorkerThread.MainForm:=Self;
WorkerThread.OnUpdate:=LetsUpdate;
WorkerThread.Start;
end;
end;
procedure TAndroidModule1.StopBtnClick(Sender:TObject);
begin
WorkerThread.Terminate;
end;