Memory leak là gì cách tránh memory leak c++
Một trong những thứ mà dev tìm hiểu đầu tiên khi bắt đầu lập trình Android nhưng cũng hay bỏ qua nhất đó chính là Context.
Show
4,
5,
6,
7,
8,
9 là những thuật ngữ thường được liên kết với Context. Hiển thị Toast, mở màn hình mới, tạo view mới hoặc lưu dữ liệu trong preferences là tất cả các hành động yêu cầu sử dụng Context làm đối số. Đôi khi giải pháp rất đơn giản (như sử dụng
0 nếu chúng ta đang ở trong một
1 ), nhưng những lúc khác, chúng ta không chắc mình đang làm gì và chúng ta vẫn tự hỏi về điều đó… Mục Lục What is the Context?An interface to the application environment. Đậu xanh… OK… nhưng điều đó có nghĩa là gì…Định nghĩa đó đang muốn nói với chúng ta rằng Context là một lớp có các phương thức để truy cập tài nguyên ứng dụng và dịch vụ hệ thống. Để có được Context, chúng ta thường sử dụng
1 (this) vì vậy, chúng ta có thể suy luận rằng
1 chính là một
4. Và thực tế thì Activity, Service hoặc Application là những triển khai cụ thể của lớp trừu tượng Context. Bên trong một ứng dụng có thể có một số Activities, một số Services và do đó, nhiều hơn một Context, nhưng chỉ có một Ứng dụng và do đó thì chỉ có một
Context dùng để làm gì?Các tình huống phổ biến nhất khi chúng ta cần sử dụng Context là khi sử dụng các Views (
4,
5,
7), khởi chạy Activities (
8,
1). Nếu bạn đang tìm kiếm một cách phân loại chính thức hơn, thì có 4 loại sau:
Có ba phương thức trả về một Context, chúng nằm trong các views, các activities và lớp
2, và mọi phương thức trong số chúng đều có chức năng riêng của nó. Trong một viewLớp View có phương thức
3 để lấy Context của Activity chứa nó. Là một Activity Context chứ không phải là một Application Context, nó có thể có thông tin về các chủ đề cụ thể làm thay đổi tính thẩm mỹ của activity cụ thể nào đó. Do đó, Activity Context là thứ cần thực hiện khi quản lý chế độ views, inflating layouts , khởi chạy activities, hiển thị dialog hoặc sử dụng các lớp ngắn hạn. Hiểu thế nào cho đúng “lớp ngắn hạn” : classLifespan <= activityLifespan Trong một activityLớp Activity là một kết thừa Context. Đây là Activity Context đã đề cập trước đó, chúng ta có thể truy cập nó bằng cách sử dụng từ khóa
0. Phương thức bạn có thể sử dụng để lấy một Context khác là
5, như tên của nó, trả về context của ứng dụng, không phải của activity. Đây là Context của quá trình mà các activities chạy và nó được sử dụng trong các lớp vượt quá tuổi thọ của Activities, chẳng hạn như các tác vụ nền ( background tasks) hoặc quyền truy cập dữ liệu (data access). Trong ContextWrapperĐây là một lớp trung gian trong cây kế thừa và cung cấp phương thức
6. Khuyến khích là KHÔNG nên sử dụng nó cho dù là mục đích gì đi nữa. Túm cái váy lại thìTrong bảng này, chúng ta có sự kết hợp giữa các hành động với các loại Context.Học cách quản lý đúng Context là một kỹ năng sẽ cứu chúng ta khỏi những vấn đề không mong muốn và điều đó có liên quan chặt chẽ với việc memory leak. Đó là lý do tại sao 2 thứ tưởng chừng không liên quan đến nhau lại ở trong 1 bài viết. Memory LeaksMemory Leaks là gì? Memory Leaks xảy ra khi bộ thu gom rác phân bổ bộ nhớ cho một đối tượng nhưng không bao giờ thu hồi nó. Bộ thu gom rác nghĩ rằng đối tượng vẫn cần thiết vì nó được tham chiếu bởi các đối tượng khác, nhưng những tham chiếu đó lẽ ra đã được xóa. Nếu điều này tiếp tục diễn ra, hệ thống có thể hết bộ nhớ heap và ứng dụng bị treo Làm thế nào để tránh memory leaks trong Android?Nguyên nhân phổ biến của memory leaks là các biến
7 , mẫu
8, tác vụ nền và các
9. Hãy xem một số ví dụ về cách phát hiện và khắc phục chúng Static variable
Trong ví dụ này, biến tĩnh
4 có tham chiếu đến
3 của
6:
Nếu ứng dụng tiếp tục chạy sau khi Acitivity bị destroy, bộ nhớ nó đang sử dụng sẽ không được giải phóng vì biến
4 có tham chiếu đến context của activity. Một giải pháp là bỏ tham chiếu đến biến bên trong phương thức
8.
Vấn đề tương tự có thể xảy ra nếu, khi sử dụng
8, nó đang lưu Activity Context. Thông thường, giải pháp tốt nhất, trong trường hợp đó, là sử dụng application context vì chúng ta được cho là ưa dùng kiến trúc như MVP, MVVM, do đó không cần truy cập trực tiếp vào các views và không cần activity context.
Inner class
0 là những lớp được tạo bên trong một lớp hoặc phương thức khác. Nếu chúng ta tạo inner class trong một Activity, thì inner class đó sẽ giữ một tham chiếu đến context của activity đó
Biến innerClass là tĩnh. Nếu nó là động, sự cố sẽ biến mất (say good bye):
Background taskMột tác vụ không đồng bộ có thể truy cập một activity và vẫn tiếp tục chạy nền sau khi activity đã chết. Trong đoạn code này, một AsyncTask được tạo bên trong một activity:
Một lần nữa, vấn đề là chúng ta đang tạo một
1. Nếu chúng ta đặt chung code bên trong một lớp kế thừa
2, vấn đề sẽ không còn nữa. Để chạy MyAsyncTask
Một Thread có thể dẫn đến cùng một sai lầm tương tự như trên , chúng ta có thể
3 luồng khi activity bị hủy để an toàn hơn:
Nhiều bạn có thể nghĩ là giờ người ta dùng coroutines , rx hết rời ai còn đi dùng mấy cái bị deprecated này làm gì. Nhưng thực tế rất nhiều dự án từ lâu đời vẫn dùng chúng để thực hiện các tác vụ đồng bộ và việc bảo trì luôn cần sự hiểu biết đúng đắn về những thứ base nhất như vậy. Xác định lifecycle owner
Ở trên sẽ gây ra memory leak vì chúng ta đã truyền
0 với tư cách là lifecycle owner. Nếu view bị hủy (
5 được gọi) nhưng fragment thì không, (
8 không được gọi), thì mọi thay đổi đối với đối tượng LiveData vẫn được quan sát và có thể gây ra sự cố bất ngờ
0
1 Khi sử register listenerĐảm bảo unregister tất cả các
9,
0, etc. theo vòng đời thích hợp để tránh memory leak. ví dụ. Nếu receiver được đăng ký trong
1, thì nó phải được hủy đăng ký trong
2 Vậy làm thế nào để xác định memory leaks khi code ?
Thêm thằng này vào file build.gradle :
3 Bây giờ hãy chạy ứng dụng. Mở qua mở lại các fragment và activitity. Cố gắng tạo thật nhiều object. Bạn sẽ thấy thông báo khi có bất kỳ rò rỉ nào đáng ngờ như bên dưới: |