【问题标题】:Android NDK: How to clean up native code after restarting activity?Android NDK:重新启动活动后如何清理本机代码?
【发布时间】:2011-04-28 19:38:12
【问题描述】:
全部,
我知道,默认情况下,当屏幕方向改变或滑入或滑出键盘时,活动将被终止并重新启动。 (见Activity restart on rotation Android)。我的问题是,从本机代码的角度来看,处理这个问题的正确方法是什么?例如如果我有一个加载本机库的静态块并且我的应用程序重新启动,我如何确保正确处理本机领域的任何内存?问题是
当我们旋转设备时,它看起来
就像创建了一个单独的线程池
旧的永远不会被删除。
这意味着每次有人
转动设备,我们还有很多
线程闲置并占用
记忆
如何确保不会发生这种情况?我从JNIExample page看到底部的一些注释:
[*]未解决的问题和错误
虽然这个例子是完全
功能性的,有几个
剩下的未解决的问题,我
到目前为止无法弄清楚。
启动时出现问题
活动,然后按返回按钮
隐藏它,然后重新启动它。
以我的经验,打电话给本地人
在此类重新启动的活动中的功能
会严重失败。调用无效()
只是因为分段而崩溃
错误,同时调用 getNewData() 和
getDataString() 导致 JVM 中止
有错误,因为它不再是
对全局缓存的对象感到满意
参考。看来活动
重新启动以某种方式使我们的缓存无效
对象引用,即使它们
受 NewGlobalRef() 保护,并且
活动在
原始 JVM(活动重启确实
并不意味着 JVM 本身就是
重新启动)。我没有好
解释为什么会发生这种情况,所以如果
你有什么想法,请让我
知道。
这个问题解决了吗?
【问题讨论】:
标签:
java
android
java-native-interface
native
android-ndk
【解决方案1】:
在 Android NDK 中重新启动很烦人。您拥有的任何静态数据都会保留,因为它会重用该过程,因此您需要手动重置在新运行时无效的任何内容(例如任何 OpenGL 纹理或顶点缓冲区对象)。它还为您提供了一个新的 Java 线程和新的 Java 应用程序以及其他对象,因此对于在您的应用程序的新实例中可能是新的对象的任何缓存全局引用也需要清除。
所以我使用的策略是双重的:最小化重新启动,并在重新启动时对所有内容进行核对。
您可以通过在应用程序中处理 configChanges 来最大程度地减少重新启动,正如它在您链接的问题的答案中所说的那样。然后打开键盘或旋转不会导致应用重新启动,这对于任何具有重要启动时间的应用都应该如此。
当我检测到我的应用程序的新实例已经启动时,我会从旧实例中释放所有关键的东西,包括释放我通过 NewGlobalRef 持有的所有 Java 对象。我试图最小化静态数据,但是当我检测到新实例正在启动时,我会在静态对象周围保留一些不可避免的地方。
一旦不再有对旧线程的未完成引用(即,一旦您释放了所有 NewGlobalRef 对象),旧线程就应该消失。
【解决方案2】:
如果 VM 重新启动,您将从头开始。如果不是,则状态就在您离开的位置。从 NewGlobalRef 下抽出东西的缓存对象引用没有失效。我写了一些关于 wooyd 文章 on the NDK mailing list 的其他注释。
如果您的 Activity 重新启动时需要初始化数据,您应该向您的 Activity 添加显式初始化调用(我认为是在 onCreate 中)。确保正确丢弃上一轮保留的所有内容——DeleteLocalRef 然后存储 NULL,不要只是 memset() 为零。