Android NDK: как очистить собственный код после перезапуска активности? - PullRequest
7 голосов
/ 21 октября 2010

All

Мне известно, что по умолчанию действие будет прекращено и перезапущено при изменении ориентации экрана или при вставке или извлечении клавиатуры. (См. Активность перезапускается при ротации Android ). Мой вопрос: как правильно справиться с этим с точки зрения нативного кода? например если у меня есть статический блок, загружающий нативную библиотеку, и мое приложение перезапускается, как мне обеспечить, чтобы с любой памятью на нативной земле обращались соответствующим образом? Проблема в

Когда мы поворачиваем устройство, оно выглядит как создается отдельный пул потоков и старые никогда не удаляются. Это означает, что каждый раз, когда кто-то крутит девайс, у нас тонны больше нити сидят без дела и берут память

Как я могу гарантировать, что этого не произойдет? Я вижу со страницы JNIExample некоторые заметки внизу:

[*] Нерешенные проблемы и ошибки Даже хотя пример полностью функционал, есть пара остаются нерешенные вопросы, которые я не смог выяснить до сих пор. Проблемы появляются при запуске активность, затем нажмите кнопку Назад чтобы скрыть это, а затем запустить его снова. По моему опыту звонки на родные функции в такой возобновленной деятельности эффектно провалится. callVoid () просто вылетает с сегментацией ошибка, в то время как вызовы getNewData () и getDataString () приводит к прерыванию работы JVM с ошибкой, потому что больше нет доволен глобально кэшированным объектом ссылка. Похоже, что активность перезагрузка как-то делает недействительным наш кэшированный ссылки на объекты, даже если они защищены с помощью NewGlobalRef (), и деятельность проходит в пределах исходная JVM (перезапуск активности не означает, что сама JVM перезапущен). У меня нет хорошего объяснение того, почему это происходит, так что если у вас есть идеи, пожалуйста, дайте мне знаю.

Это было решено?

Ответы [ 2 ]

7 голосов
/ 22 октября 2010

Перезапуск в Android NDK раздражает. Любые статические данные, которые у вас есть, задерживаются, потому что они повторно используют процесс, поэтому вам нужно вручную сбросить все, что будет недопустимым при новом запуске (например, любые объекты текстуры OpenGL или буфера вершин). Он дает вам новый поток Java, а также новое приложение Java и другие объекты, поэтому любые кэшированные глобальные ссылки на объекты, которые будут новыми в новом экземпляре вашего приложения, также необходимо очистить.

Таким образом, стратегия, которую я использую, имеет два аспекта: минимизировать перезапуски и уничтожать все при перезапуске.

Вы минимизируете перезапуски, обрабатывая в приложении configChanges, как сказано в ответе на вопрос, который вы связали. Тогда открытие клавиатуры или вращение не вызывают перезапуск приложения, как это должно быть для любого приложения с нетривиальным временем запуска.

И когда я обнаруживаю, что новый экземпляр моего приложения запущен, я освобождаю все критически важные от старого экземпляра в тот момент, включая освобождение любых объектов Java, которые я держал через NewGlobalRef. Я пытался минимизировать статические данные, но в нескольких неизбежных местах, где я храню статические объекты, я очищаю их при обнаружении запуска нового экземпляра.

Старые потоки должны исчезнуть, как только на них больше не останется выдающихся ссылок (т. Е. После того, как вы освободите все свои объекты NewGlobalRef).

2 голосов
/ 22 октября 2010

Если виртуальная машина перезапущена, вы начинаете с нуля. Если нет, то штат находится там, где вы его оставили. Нет недействительности ссылок на кешированные объекты, которые вытаскивают вещи из-под NewGlobalRef. Я написал несколько других заметок о статье wooyd в списке рассылки NDK .

Если у вас есть данные, которые нужно инициализировать при перезапуске вашей активности, вы должны добавить явный вызов инициализации к вашей активности (я думаю, в onCreate). Удостоверьтесь, что вы правильно отбросили все материалы, оставшиеся в предыдущем раунде - DeleteLocalRef, затем сохраните NULL, а не только memset () в ноль.

...