2010-12-27 38 views
7

Trong mã nguồn của Activity.java, tôi thấy một số phương pháp dưới đây:Tránh nội Getters/setters

public View findViewById(int id) { 
    return getWindow().findViewById(id); 
} 

và định nghĩa của phương pháp GetWindow:

public Window getWindow() { 
    return mWindow; 
} 

Nhưng như các quy tắc sau đây:

Tránh nội Getters/setters

Trong các ngôn ngữ bản địa như C++, nó là thực hành phổ biến để sử dụng getters (ví dụ: i = getCount()) thay vì truy cập trực tiếp vào trường (i = mCount). Đây là một thói quen tuyệt vời cho C++, bởi vì trình biên dịch thường có thể truy cập vào quyền truy cập và nếu bạn cần hạn chế hoặc truy cập trường gỡ lỗi, bạn có thể thêm mã bất kỳ lúc nào.

Trên Android, đây là một ý tưởng tồi. Cuộc gọi phương thức ảo rất tốn kém, nhiều hơn so với trường hợp ví dụ tra cứu. Việc theo dõi lập trình hướng đối tượng phổ biến thực hành và có getters và setters trong giao diện công khai, nhưng trong một lớp học bạn phải luôn truy cập trực tiếp vào các trường .

Nếu không có JIT, truy cập trực tiếp vào trường là khoảng 3x nhanh hơn gọi số getter tầm thường. Với JIT (trong đó truy cập trực tiếp trường có giá rẻ như truy cập một địa phương), trường trực tiếp quyền truy cập nhanh hơn khoảng 7x so với gọi trình thu thập nhỏ. Đây là đúng trong Froyo, nhưng sẽ cải thiện trong tương lai khi JIT vạch ra phương thức getter .

vì vậy tôi muốn biết lý do tại sao nhà phát triển Android không truy cập trực tiếp đối tượng mWindow này? Nếu JIT của các phiên bản Android hiện tại không thể truy cập nội tuyến, getWindow(). FindViewById (id) sẽ tốn nhiều thời gian hơn mWindow.findViewById (id) và findViewById là một phương thức khá thường xuyên được sử dụng.

Trả lời

1

Bạn không thể truy cập trực tiếp vào thuộc tính mWindow - it's private. Và tôi sẽ không quan tâm đến tốc độ của findViewById, vì bạn chỉ cần gọi nó một lần cho mỗi chế độ xem trong bố cục của bạn theo phương pháp onCreate() và lưu trữ lượt xem trong các thành viên hoạt động của bạn. Bạn do gọi findViewById chỉ một lần cho mỗi lượt xem, đúng không? ;-)

Tuy nhiên, nếu bạn thực sự quan tâm đến những điều này, bạn có thể gọi getWindow() cho chính mình, lưu nó vào biến cục bộ và gọi trực tiếp findViewById trên đó. Tôi sẽ không khuyên bạn nên điều này bởi vì tất cả các gia tăng hiệu suất của bạn ở đây không đáng giá thời gian và dù sao cũng sẽ lỗi thời với các phiên bản tương lai của JIT.

Nếu bạn làm điều này tôi sẽ rất quan tâm đến số lượng micro giây bạn đã lưu. :-)

+0

Cảm ơn bạn trả lời. Tôi chắc chắn gọi findViewById một lần cho mỗi lần xem như bạn đã nói. Có lẽ tôi đã hiểu lầm nguyên tắc, và bây giờ nó rõ ràng. – teok

2

Đầu tiên: bạn không thể truy cập vì nó ở chế độ riêng tư.

Tại sao riêng tư?

Như bạn đã nói, việc truy cập thành viên trực tiếp nhanh hơn. Mặt khác, bạn đang gọi một phương thức không phải là rất nhanh vì nó sẽ tra cứu một số khung nhìn trong hệ thống phân cấp khung nhìn. Vì vậy, bằng cách sử dụng một phương pháp thay vì truy cập trực tiếp sẽ phải chịu một chi phí nhỏ về tỷ lệ phần trăm của tổng thời gian cần thiết để thực hiện nhiệm vụ đó.

Dù sao, tôi tin rằng lý do cho việc này là đóng gói.

Bạn đang gọi một số thứ bạn không sở hữu (đó là SDK Android). Vì vậy, bạn không nên đưa ra bất kỳ giả định nào về những gì đang xảy ra "ở phía bên kia". Đơn giản chỉ cần sử dụng phương pháp này và hy vọng rằng nó sẽ trả lại quan điểm bạn muốn (hoặc null nếu nó không tồn tại).

Có thể phiên bản Android tiếp theo sẽ sử dụng một phương pháp khác để tra cứu chế độ xem, chứ không gọi số getWindow(). Nếu bạn sử dụng phương pháp này, họ (Google/Android) có thể chỉ đơn giản là đánh dấu phương thức là không được chấp nhận và "chuyển tiếp" yêu cầu của bạn đến triển khai mới nhất. Nếu bạn gọi trực tiếp getWindow(), có thể bạn sẽ tìm kiếm thứ gì đó không còn được đặt trong đó nữa.

+0

Tôi không cần phải gọi getWindow() tất cả thời gian để đánh giá thành viên xem. Tuy nhiên, chúng tôi là khách hàng cho android apis, tôi muốn biết tại sao họ đã viết mã như vậy, tại sao không phải điều này, nó là một cái gì đó giá trị mà tôi quan tâm. Và cảm ơn bạn đã trả lời. – teok

+0

Bạn không hiểu tôi đúng. Trong gigerbread, findView có thể sử dụng thông tin được lưu trữ ở đâu đó trong đối tượng cửa sổ. Tổ ong google có thể quyết định thay đổi hệ thống phân cấp khung nhìn và lưu trữ thông tin tương ứng ở một nơi khác, với định dạng khác bằng cách sử dụng các cấu trúc dữ liệu khác. Nếu bạn sử dụng cửa sổ trực tiếp, nó sẽ không hoạt động trong phiên bản mới. Nếu bạn sử dụng findView, google có thể gọi triển khai mới. Thông tin thêm: http://en.wikipedia.org/wiki/Encapsulation_(object-oriented_programming) –

+0

liên kết cuối cùng của tôi phải là http://en.wikipedia.org/wiki/Encapsulation_(object-oriented_programming%29 –

0

Chúng tôi có một lý do để mỉm cười bây giờ ...

Các tài liệu android mà nói để tránh thu khí nội bộ và setters sẽ thay đổi sớm, được cho là progruard đã được thêm vào nền tảng Gingerbread mà làm một công việc tốt của nội tuyến accessor, xin vui lòng tham khảo "Avoid Internal Getters/Setters" is bad advice và hai bài đăng SO này.

  1. https://stackoverflow.com/a/6716573/892055

  2. https://stackoverflow.com/a/4930538/892055

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