2011-02-06 33 views
15

Tôi đang viết chế độ xem tùy chỉnh mở rộng trực tiếp android.view.View. Nếu tôi cố gắng truy cập vào các trường mScrollX hoặc mScrollY, tôi thấy lỗi rằng trường "không thể được giải quyết hoặc không phải là một trường". source code for android.view.View có mScrollX, mScrollY và các biến tương tự được khai báo protected. Làm thế nào mà lớp con trực tiếp của tôi không thể truy cập các trường được bảo vệ của lớp cha của nó? (Các lớp như ScrollView dường như có thể.)Các trường được bảo vệ không hiển thị với các lớp con

P.S. Tôi nhận ra rằng tôi có thể gọi số getScrollX(), nhưng tôi muốn cập nhật các trường này; gọi setScroll() có các tác dụng phụ mà tôi không muốn.

+0

Lạ, lớp con, ngay cả trong các gói khác, có thể truy cập các biến được bảo vệ của siêu lớp của chúng. Tôi đoán rằng bạn đang sử dụng phiên bản sai. Bạn có thể hiển thị một số mã của bạn không? –

+0

Hành vi được xác nhận. –

Trả lời

20

Đó là vì chúng không phải là một phần của Android SDK.

Đây là mã nguồn cho mScrollX:

/** 
* The offset, in pixels, by which the content of this view is scrolled 
* horizontally. 
* {@hide} 
*/ 
@ViewDebug.ExportedProperty(category = "scrolling") 
protected int mScrollX; 

Bạn sẽ thấy @hide chú thích. Điều đó có nghĩa đây không phải là một phần của Android SDK. Một phần của quá trình xây dựng tạo SDK Android sẽ không bao gồm thành viên dữ liệu này trong ấn bản sơ khai là android.view.View có trong tệp android.jar mà bạn đang biên soạn.

Chú thích @hide được sử dụng cho những mục đích cho mục đích nội bộ cần được công khai hoặc được bảo vệ nhưng không được coi là điều mà nhà phát triển SDK nên sử dụng.

Vui lòng tìm các giải pháp khác cho bất kỳ vấn đề nào bạn đang gặp phải.

+9

Hmm, thú vị! Vì vậy, để diễn giải lý do: "Chúng tôi không thể bận tâm để sắp xếp đóng gói thích hợp, vì vậy chúng tôi đã hủy bỏ ngôn ngữ." ... –

+0

Tôi đã nhận thấy thẻ '{@hide}'. Tôi cho rằng đó là lý do tại sao 'mScrollX' không xuất hiện trong JavaDocs (như [thẻ' @ exclude' được đề xuất] (http://java.sun.com/j2se/javadoc/proposed-tags.html), mà supercedes ' @ hide'). Tôi đã không nhận ra rằng SDK là một phiên bản sơ khai của API. –

+0

Một điều tôi không thể hiểu là Protected variable của ** View ** class được truy cập trong ** lớp ScrollView **. Sao có thể như thế được ? Cấu trúc phân cấp là - ScrollView mở rộng FramLayout mở rộng ViewGroup mở rộng Xem. Vì vậy, biến bảo vệ của lớp View chỉ nên truy cập trong ViewGroup. –

5

Rất thẳng về phía trước: chú ý chú thích @hide phía trên các biến này. Đó là chú thích dành riêng cho Android ẩn các trường/phương thức khỏi SDK công khai. Đó là lý do tại sao bạn không thể truy cập chúng trực tiếp.

Romain Guy mentioned it in bài đăng này.

+0

gây phiền toái. điểm nguồn mở là gì? để mọi người có thể đọc nguồn và hiểu những gì đang diễn ra. nhưng nguồn phát hành ở đây là một nguồn giả mạo? không phải cái được sử dụng trong sản xuất? cũng có thể chấp nhận được, * nếu nó trong suốt *.Tôi không quan tâm nếu nguồn JDK là nguồn * thực *, nhưng bất kỳ thông tin nào tôi thu được từ đọc nó đều đúng trong hệ thống thực. – irreputable

+0

Bạn phải hiểu ý nghĩa của nguồn mở. Trước hết, bạn có thể xây dựng phiên bản Android của riêng bạn trực tiếp từ nguồn, thực hiện bất kỳ sửa đổi nào bạn muốn và sử dụng mọi phương thức hoặc trường cho dù có ẩn hay không. Đó là những gì các nhà sản xuất điện thoại làm và một số đầu bếp ROM tùy chỉnh trong cộng đồng. Các nhà phát triển có thể hưởng lợi từ khía cạnh khác của Android là nguồn mở, và điều đó đang trải qua nguồn và hiểu cách mọi thứ hoạt động sau hậu trường, đối với tôi điều này cũng quan trọng như bản thân tài liệu. – Lior

+2

Thực tế là một số trường hoặc phương thức bị ẩn thường là một trong hai trường sau: 1. Chúng có thể thay đổi trong bản phát hành SDK trong tương lai, vì vậy, chúng muốn giảm cơ hội không tương thích với ứng dụng, giúp bạn tiết kiệm rất nhiều làm việc duy trì các ứng dụng của bạn và 2. Sử dụng các trường này trực tiếp như trong trường hợp của bạn có thể ảnh hưởng đến công việc thích hợp về cách hoạt động của API trong nội bộ. – Lior

4

Bạn có thể thử thiết lập các lĩnh vực với sự phản ánh:

import java.lang.reflect.Field; 

// ... 

try { 
    Field scrollXField = View.class.getDeclaredField("mScrollX"); 
    scrollXField.setAccessible(true); 
    scrollXField.set(this, myNewValue); 
} catch (Exception ex) { 
    // oops, android changed the implementation. sucks to be you. 
} 

Lưu ý, tuy nhiên, bạn đang dựa vào hành vi không có giấy tờ và không được hỗ trợ khi bạn làm điều này, và do đó bạn nên chuẩn bị cho những thứ để phá vỡ trên một số thiết bị hoặc trong các phiên bản sau.

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