如果我使用任何RoboVM非空参数调用以下方法:
public static void runOnUiThread(final Runnable runnable) {
System.out.println("Inside runOnUiThread():");
System.out.println(" Null-check: "+(runnable==null));
NSOperation operation = new NSOperation() {
@Override
public void main() {
System.out.println("Inside main():");
System.out.println(" Null-check: "+(runnable==null));
runnable.run(); // NullPointerException here?!? How???
System.out.println(" main() completed");
}
};
NSOperationQueue.getMainQueue().addOperation(operation);
}它的产出如下:
Inside runOnUiThread():
Null-check: false
Inside main():
Null-check: true
java.lang.NullPointerException
at RoboVMTools$1.main(RoboVMTools.java)
at org.robovm.apple.foundation.NSOperation.$cb$main(NSOperation.java)
at org.robovm.apple.uikit.UIApplication.main(Native Method)
at org.robovm.apple.uikit.UIApplication.main(UIApplication.java)
at Main.main(Main.java)到底怎么回事?更重要的是,我该如何解决这个问题呢?
operation.addStrongRef(runnable);之前添加NSOperationQueue...。没什么区别。private final字段的自己的类中,以存储传递给构造函数的runnable。同样的结果。我是不是错过了一些显而易见的东西?
发布于 2015-06-07 07:06:54
你说的GC是对的。在从Objective端调用操作之前,您的NSOperation实例是垃圾收集的。当NSOperationQueue调用到NSOperation端时,将创建一个新的NSOperation匿名类实例,它没有对Runnable实例的引用,而是对null的引用,其结果是抛出一个NullPointerException。
使用addStrongRef()解析它的方式是正确的,不过只有mainQueue.addStrongRef(operation)和相应的removeStrongRef()调用就足够了:
public static void runOnUiThread(final Runnable runnable) {
final NSOperationQueue mainQueue = NSOperationQueue.getMainQueue();
NSOperation operation = new NSOperation() {
@Override
public void main() {
runnable.run();
mainQueue.removeStrongRef(this);
}
};
mainQueue.addStrongRef(operation);
mainQueue.addOperation(operation);
}这将防止Java实例(以及任何像operation一样可以从它访问的Runnable对象)成为GCed,直到目标-C NSOperationQueue实例被释放为止。由于目标-C侧队列是一个单例,它在应用程序的生命周期内不会被释放。
RoboVM NSOperationQueue类提供了接受Runnable的addOperation()方法的一个版本。在使用此方法时,RoboVM将负责保留Runnable实例,而目标-C端则需要它。对于任何接受@Block注解参数类型的Runnable或任何org.robovm.objc.block.VoidBlock*或org.robovm.objc.block.Block*接口的方法,也是如此。
使用这个addOperation()方法,您的代码就变成了:
public static void runOnUiThread(Runnable runnable) {
NSOperationQueue.getMainQueue().addOperation(runnable);
}PS。RoboVM使用的GC与苹果垃圾收集器无关,因此苹果的文档不会帮助您理解这样的问题。
发布于 2015-06-07 01:19:37
好吧..。这就解决了以下问题:
public static void runOnUiThread(final Runnable runnable) {
final NSOperationQueue mainQueue = NSOperationQueue.getMainQueue();
NSOperation operation = new NSOperation() {
@Override
public void main() {
runnable.run();
mainQueue.removeStrongRef(runnable);
mainQueue.removeStrongRef(this );
}
};
mainQueue.addStrongRef(runnable );
mainQueue.addStrongRef(operation);
mainQueue.addOperation(operation);
}但别问我为什么要这么做。Apple是这么说的,正如我之前尝试的那样,“在垃圾收集应用程序中,队列强烈引用操作对象。”,operation.addStrongRef(runnable);应该已经足够了,因为操作对象应该被队列引用。但是我想这个世界并不总是像我解释文档那样工作。
https://stackoverflow.com/questions/30688370
复制相似问题