2010-10-21 33 views
7

Tất cả,NDK của Android: Cách xóa mã gốc sau khi khởi động lại hoạt động?

Tôi biết rằng theo mặc định, hoạt động sẽ bị giết và khởi động lại khi hướng màn hình thay đổi hoặc bàn phím được trượt vào hoặc ra. (Xem Activity restart on rotation Android). Câu hỏi của tôi là, cách chính xác để xử lý điều này từ phối cảnh mã Native là gì? ví dụ. nếu tôi có một khối tĩnh tải một thư viện gốc và ứng dụng của tôi được khởi động lại, làm thế nào để đảm bảo rằng bất kỳ bộ nhớ nào trong vùng đất bản địa được xử lý một cách thích hợp? Vấn đề là

Khi chúng tôi xoay thiết bị, có vẻ như giống như một hồ bơi Chủ đề riêng được tạo ra và cũ không bao giờ bị xóa. này có nghĩa là mỗi khi ai đó biến thiết bị, chúng tôi có nhiều hơn một tấn đề ngồi nhàn rỗi và chiếm nhớ

Làm thế nào để đảm bảo rằng điều này không xảy ra? Tôi nhìn thấy từ JNIExample page một số ghi chú ở phía dưới:

[*] vấn đề không được giải quyết và lỗi Thậm chí dù ví dụ này là hoàn toàn chức năng, có một vài vấn đề chưa được giải quyết còn lại, mà tôi đã không thể tìm ra cho đến nay. Sự cố xuất hiện khi bạn bắt đầu hoạt động , sau đó nhấn nút Quay lại để ẩn nó và sau đó bắt đầu lại. Theo kinh nghiệm của tôi, các cuộc gọi đến các chức năng gốc trong hoạt động được khởi động lại như vậy sẽ không thành công một cách ngoạn mục. callVoid() chỉ đơn giản là treo với một lỗi segmentation , trong khi các cuộc gọi đến getNewData() và getDataString() nguyên nhân JVM để hủy bỏ với một lỗi, bởi vì nó không còn hài lòng với cache trên toàn cầu đối tượng tham khảo. Có vẻ như hoạt động khởi động lại bằng cách nào đó làm mất hiệu lực tham khảo cache đối tượng của chúng tôi, mặc dù họ được bảo vệ với NewGlobalRef(), và hoạt động đang chạy trong gốc JVM (hoạt động khởi động lại không không có nghĩa là JVM chính nó là khởi động lại) . Tôi không có giải thích rõ ràng về lý do xảy ra, vì vậy nếu bạn có bất kỳ ý tưởng nào, vui lòng cho tôi biết.

Điều này đã được giải quyết chưa?

Trả lời

6

Khởi động lại trong Android NDK gây phiền toái. Bất kỳ dữ liệu tĩnh nào bạn có xung quanh, vì nó sử dụng lại quy trình, vì vậy bạn cần phải đặt lại theo cách thủ công mọi thứ sẽ không hợp lệ trên một lần chạy mới (giống như bất kỳ đối tượng bộ đệm OpenGL hoặc vertex nào).Nó cung cấp cho bạn một luồng Java mới và Ứng dụng Java mới cũng như các đối tượng khác, vì vậy mọi tham chiếu toàn cục được lưu trong bộ nhớ cache đối với các đối tượng sẽ là mới trong một thể hiện ứng dụng mới của bạn cũng cần được xóa.

Vì vậy, chiến lược tôi sử dụng là gấp đôi: Giảm thiểu khởi động lại và nuke mọi thứ khi khởi động lại.

Bạn giảm thiểu việc khởi động lại bằng cách xử lý các cấu hình trong ứng dụng, như trong câu trả lời cho câu hỏi bạn đã liên kết. Sau đó, mở bàn phím hoặc xoay không khiến ứng dụng khởi động lại, điều này cũng giống như ứng dụng bất kỳ với thời gian khởi động không nhỏ.

Và khi tôi phát hiện thấy một phiên bản ứng dụng mới của tôi đã bắt đầu, tôi phát hành mọi thứ quan trọng từ cá thể cũ tại thời điểm đó, bao gồm phát hành bất kỳ đối tượng Java nào mà tôi đã nắm giữ qua NewGlobalRef. Tôi đã cố gắng để giảm thiểu dữ liệu tĩnh, nhưng vài nơi không thể tránh khỏi mà tôi giữ xung quanh các đối tượng tĩnh tôi xóa chúng khi tôi phát hiện các trường hợp mới bắt đầu lên.

Chủ đề cũ sẽ biến mất khi không có thêm tham chiếu nào nổi bật cho chúng (nghĩa là khi bạn đã phát hành tất cả các đối tượng NewGlobalRef của mình).

2

Nếu VM khởi động lại, bạn bắt đầu từ đầu. Nếu không, tiểu bang là đúng nơi bạn rời khỏi nó. Không có sự không hợp lệ của các tham chiếu đối tượng được lưu trong bộ nhớ đệm mà yanks từ bên dưới NewGlobalRef. Tôi đã viết một vài ghi chú khác về bài viết wooyd on the NDK mailing list.

Nếu bạn có dữ liệu cần được khởi chạy khi hoạt động của bạn được khởi động lại, bạn nên thêm lệnh gọi khởi tạo rõ ràng vào hoạt động của mình (trong phần Tạo, tôi nghĩ). Hãy chắc chắn rằng bạn loại bỏ bất kỳ thứ gì bạn giữ lại từ vòng trước - DeleteLocalRef sau đó lưu trữ NULL, không chỉ memset() bằng 0.

Các vấn đề liên quan