gpt4 book ai didi

android - 如何正确清理 Android 监听器?

转载 作者:搜寻专家 更新时间:2023-11-01 08:28:55 26 4
gpt4 key购买 nike

在 Android 下,我们可以声明一些监听器,如下例所示:

TErrorListener = class(TJavaLocal, JMediaPlayer_OnErrorListener)
private
public
function onError(mp: JMediaPlayer; what: Integer; extra: Integer): Boolean; cdecl;
end;

TmyObject = class
private
FMediaPlayer: jmediaplayer;
FOnErrorListener: TErrorListener;
end;

然后我们可以像这样激活OnErrorListener:

FMediaPlayer.setOnErrorListener(FOnErrorListener);

但是,停用这样的OnErrorListener是有问题的。

在 Delphi 中,Android UI 线程和主线程是不同的线程,onError 将在 Android UI 线程的上下文中调用,因为底层 Java 框架中有这个函数:

  //   Looper looper;
// if ((looper = Looper.myLooper()) != null) {
// mEventHandler = new EventHandler(this, looper);
// } else if ((looper = Looper.getMainLooper()) != null) {
// mEventHandler = new EventHandler(this, looper);
// } else {
// mEventHandler = null;
// }

在主线程中设置 FMediaPlayer.setOnErrorListener(nil); 可能会导致问题,因为它不同于可能正在对内部变量 mOnErrorListener 执行某些操作的 UI 线程。

我尝试将停用与以下代码同步:

  CallInUIThreadAndWaitFinishing(
procedure
begin
FMediaPlayer.setOnErrorListener(nil);
end);

但是,有时应用程序会在此时崩溃,我不知道为什么。我怎样才能避免这种情况?

最佳答案

如您所述,CallInUIThreadAndWaitFinishing 有两个重载:

TMethodCallback = procedure of object;
TCallBack = reference to procedure;

procedure CallInUIThreadAndWaitFinishing(AMethod: TMethodCallback); overload;
procedure CallInUIThreadAndWaitFinishing(AMethod: TCallBack); overload;

第一个回调是常规方法,不涉及任何特殊处理。执行后,您的代码将继续正常运行。

使用

CallInUIThreadAndWaitFinishing(aProcedureOfObject);

之所以有效,是因为在幕后没有隐藏的捕获。


第二个回调是具有特殊功能的匿名方法 - 对方法主体中使用的任何变量的强大捕获。万一

CallInUIThreadAndWaitFinishing(procedure
begin
FmyObject.dosomething
end);

它将捕获 FmyObject 变量。

这是使用匿名方法回调调用 CallInUIThreadAndWaitFinishing 的第一步。接下来发生的事情是创建 Java 可运行对象

Runnable := TRunnable.Create(AMethod);
ActiveJavaRunnables.Add(Runnable);
Runnable.Start;

以上代码将您的匿名方法 (AMethod) 存储在 TRunnable FCallback 字段中,创建对您的匿名方法以及任何变量的强引用方法捕获。

现在真正的收获来了。 Runnable 对象不会在您的代码执行时自动清除 - 它存储在 ActiveJavaRunnables 列表中并且该列表以非确定性方式定期清除 - 从某种意义上说您不知道什么时候会被清除,什么时候会真正释放 Runnable 并存储 FCallback 以及沿途捕获的所有内容。

如果你想使用匿名方法,你必须为你在匿名方法体内使用的任何对象创建临时弱引用,然后使用那个弱引用。

关于android - 如何正确清理 Android 监听器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42209444/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com