2012-04-11 38 views
7

Tôi biết rằng các lớp bên trong không được đề xuất trong Android vì chúng giữ tham chiếu đến lớp kèm theo. Tuy nhiên, trong Java, lớp ngoài chỉ được GC khi lớp bên trong không còn được tham chiếu nữa. Điều đó có nghĩa là, trong Android, miễn là bạn có tham chiếu không tĩnh trong lớp hoạt động bên ngoài cho lớp bên trong, lớp bên trong không thể tồn tại lâu hơn lớp hoạt động bên ngoài vì hoạt động chỉ có thể bị hủy nếu nó không giữ tham chiếu đến lớp bên trong nữa (ít nhất đó là những gì tôi suy luận). Vì vậy, vấn đề là gì khi sử dụng các lớp bên trong không tĩnh (vì chúng không thể tồn tại lâu hơn hoạt động bên ngoài nếu bạn suy ra từ java)? Tui bỏ lỡ điều gì vậy?Các lớp bên trong: Android và Java

Cảm ơn!

+1

Bạn đã đọc các lớp bên trong không tĩnh trong Android ở đâu? – Cristian

+0

Đây không chỉ là vấn đề Android. Đối với mã hoán đổi cho nhau và nhanh chóng, bạn nên tránh chúng ngoại trừ chúng tĩnh và lưu trữ thông tin mà chúng yêu cầu dưới dạng các trường cục bộ. Vấn đề với các lớp bên trong là bạn không thể đặt tham chiếu đến lớp cha thành 'null' để lấy nó thành GC'ed. Trình biên dịch phải tạo ra các phương thức truy cập nếu các thành viên lớp cha mà truy cập lớp bên trong là riêng và bạn có một lớp bên trong cho mỗi cá thể lớp cha. – Stephan

+0

@Cristian cuộn xuống cuối liên kết này http://developer.android.com/resources/articles/avoiding-memory-leaks.html nó là để tránh nếu bạn không thể kiểm soát vòng đời của lớp bên trong. – OckhamsRazor

Trả lời

8

Hãy xem xét ví dụ đơn giản này

class Leaker 
{ 
    public static Object leakedObj; 
} 

class MyActivity extends Activity 
{ 
    public class MyInnerClass { ... } 

    void onCreate(Bundle savedState) 
    { 
     Leaker.leakedObj = new MyInnerClass(); 
     //The activity now won't be GCed until Leaker.leakedObj is cleared.   
    } 
} 

Bạn có thể dễ dàng vượt qua một lớp học không tĩnh bên ngoài bối cảnh hoạt động của bạn. Miễn là bạn không vượt qua lớp bên trong của bạn cho các đối tượng bên ngoài vòng đời của Activity bạn sẽ không sao. Nhưng chắc chắn nó có thể làm rò rỉ hoạt động của bạn thông qua một lớp bên trong.

+0

cảm ơn justin. câu trả lời của bạn có vẻ đầy hứa hẹn. vì vậy chỉ để xác nhận- các lớp bên trong không tĩnh tồn tại lâu hơn một hoạt động nếu không có tham chiếu nào khác đến lớp bên trong ngoại trừ các tham chiếu trong hoạt động bên ngoài, tất cả đều không tĩnh? – OckhamsRazor

+0

+1 để chỉ ra vấn đề chính với các lớp bên trong tĩnh của Hoạt động: một Hoạt động có thể không được GC ở thời gian mong muốn vì một số đối tượng thứ ba (không hoạt động trong vòng đời) ở một nơi khác đang treo một tham chiếu đến một thể hiện của lớp bên trong, lần lượt chuyển sang Activity thông qua tham chiếu tổng hợp. –

+0

@OckhamsRazor, Nếu tham chiếu duy nhất cho lớp bên trong của bạn là từ Hoạt động (và tất cả đều là không tĩnh), thì Hoạt động sẽ được thu thập như bình thường. –

6

Tôi sẽ không bận tâm, vì Google có thể giải thích rõ hơn.

Giả sử: lớp chuyên là Foo và lớp bên trong là Foo$Inner:

Vấn đề là VM coi truy cập trực tiếp đến các thành viên tin Foo từ Foo $ Nội là bất hợp pháp vì Foo và Foo $ Nội có các lớp học khác nhau, mặc dù ngôn ngữ Java cho phép một lớp bên trong truy cập vào các thành viên riêng của lớp bên ngoài. Để thu hẹp khoảng cách, trình biên dịch sẽ tạo ra một vài phương pháp tổng hợp:

/*package*/ static int Foo.access$100(Foo foo) { 
    return foo.mValue; 
} 
/*package*/ static void Foo.access$200(Foo foo, int value) { 
    foo.doStuff(value); 
} 

Mã lớp bên trong gọi những phương pháp tĩnh bất cứ khi nào nó cần phải truy cập vào các lĩnh vực mValue hoặc gọi phương thức doStuff trong lớp ngoài. Điều này có nghĩa là đoạn mã trên thực sự chứa đựng một trường hợp bạn đang truy cập các trường thành viên thông qua các phương thức truy cập. Trước đó chúng tôi đã nói về cách truy cập chậm hơn truy cập trực tiếp trường, vì vậy đây là một ví dụ về một thành ngữ ngôn ngữ nhất định dẫn đến một hit "vô hình" hiệu suất hit.

Nếu bạn đang sử dụng mã như thế này trong điểm phát sóng hiệu suất, bạn có thể tránh phí trên bằng cách khai báo trường và phương thức được truy nhập bởi lớp bên trong để có quyền truy cập gói chứ không phải quyền truy cập riêng tư. Thật không may điều này có nghĩa là các trường có thể được truy cập trực tiếp bởi các lớp khác trong cùng một gói, vì vậy bạn không nên sử dụng nó trong API công cộng.

Nguồn: https://developer.android.com/training/articles/perf-tips.html#PackageInner

+0

cảm ơn, đây là nội dung thú vị. nhưng nó vẫn không trả lời câu hỏi của tôi - các lớp bên trong không tĩnh tồn tại lâu hơn một hoạt động nếu không có tham chiếu khác tới lớp bên trong ngoại trừ các tham chiếu trong hoạt động bên ngoài, không tĩnh? – OckhamsRazor

+0

@OckhamsRazor Bạn hỏi "có thể [trường hợp] các lớp bên trong không tĩnh tồn tại lâu hơn một hoạt động nếu không có tham chiếu khác tới [các thể hiện] của lớp bên trong ngoại trừ tham chiếu [không tĩnh] trong hoạt động bên ngoài?" Câu trả lời là không. –

+0

ah, tuyệt vời, cảm ơn mike, bạn đã nói tốt hơn. và đó cũng là điều tôi muốn biết. chúc mừng! – OckhamsRazor

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