Android NDK:重启活动后如何清理本机代码?

时间:2010-10-21 19:32:59

标签: java android java-native-interface native android-ndk

所有

我知道默认情况下,当屏幕方向改变或键盘滑入或滑出时,活动将被终止并重新启动。 (见Activity restart on rotation Android)。我的问题是,从Native代码的角度处理这个问题的正确方法是什么?例如如果我有一个静态块加载本机库并重新启动我的应用程序,我如何确保本地的任何内存都得到适当处理?问题是

  

当我们旋转设备时,它看起来   就像创建一个单独的线程池一样   旧的永远不会被删除。   这意味着每次都有人   转动设备,我们还有更多   线程闲置而且占用   存储器

我如何确保不会发生这种情况?我从JNIExample page底部的一些注释中看到了:

  

[*]未解决的问题和错误甚至   虽然这个例子是完整的   功能性,有一对   尚未解决的问题,我   到目前为止还没弄清楚。   启动时会出现问题   活动,然后按返回按钮   隐藏它,然后再次启动它。   根据我的经验,打电话给本地人   这种重新启动的活动中的功能   会失败的。 callVoid()   简单地用分段崩溃   错误,同时调用getNewData()和   getDataString()导致JVM中止   有错误,因为它不再存在   对全局缓存对象感到满意   参考。它似乎是活动   以某种方式重启无效我们的缓存   对象引用,即使它们   受NewGlobalRef()和   活动正在运行   原始JVM(活动重启确实   并不意味着JVM本身就是   重新启动)。我没有好处   解释为什么会发生这种情况,所以如果   你有任何想法,请让我   知道。

这已经解决了吗?

2 个答案:

答案 0 :(得分:7)

在Android NDK中重新启动很烦人。您有任何静态数据,因为它重用了该过程,因此您需要手动重置在新运行中无效的任何内容(如任何OpenGL纹理或顶点缓冲区对象)。它还为您提供了一个新的Java线程和新的Java应用程序以及其他对象,因此任何对应用程序的新实例中都是新的对象的缓存全局引用也需要清除。

所以我使用的策略是双重的:最小化重启,并在重启时核对一切。

通过处理appChanges in-app来最小化重启,正如您在链接问题的答案中所说的那样。然后打开键盘或旋转不会导致应用程序重新启动,这对于任何具有非平凡启动时间的应用程序应该是这样。

当我检测到我的应用程序的新实例已经启动时,我会在那时从旧实例中释放所有关键内容,包括通过NewGlobalRef释放我保留的任何Java对象。我试图最小化静态数据,但是当我检测到新实例启动时,我确实在静态对象周围保留了几个不可避免的地方。

旧的线程一旦没有更多未完成的引用就会消失(即,一旦你释放了所有的NewGlobalRef对象)。

答案 1 :(得分:2)

如果重新启动VM,则从头开始。如果没有,状态就在你离开的地方。在NewGlobalRef下,没有任何缓存对象引用失效的东西。我写了一些关于wooyd文章on the NDK mailing list的其他说明。

如果您在重新启动活动时需要初始化数据,则应该为您的活动添加显式初始化调用(我认为在onCreate中)。确保正确丢弃上一轮中保留的任何内容 - DeleteLocalRef然后存储NULL,不要将memset()归零。