2011-02-06 1 views
15

Я пишу пользовательский вид, который напрямую расширяет android.view.View. Если я попытаюсь получить доступ к полям mScrollX или mScrollY, я вижу ошибку, что поле «не может быть разрешено или не является полем». source code for android.view.View имеет mScrollX, mScrollY и аналогичные переменные, объявленные protected. Как мой прямой подкласс не может получить доступ к защищенным полям своего родительского класса? (Классы типа ScrollView, по-видимому, могут.)Защищенные поля, не видимые подклассам

P.S. Я понимаю, что могу позвонить getScrollX(), но я хочу обновить эти поля; вызов setScroll() имеет побочные эффекты, которые я не хочу.

+0

Странные подклассы, даже находящиеся в других пакетах, могут получить доступ к защищенным переменным своего суперкласса. Я предполагаю, что вы используете неправильную версию. Можете ли вы показать код? –

+0

Поведение подтверждено. –

ответ

20

Это потому, что они не являются частью Android SDK.

Вот исходный код mScrollX:

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

Вы заметите @hide аннотацию. Это означает, что это не часть Android SDK. Часть процесса сборки, которая создает Android SDK, не будет включать этот элемент данных в версию заглушки android.view.View, которая находится в файле android.jar, который вы компилируете.

Аннотации @hide используются для вещей, которые для внутренних целей должны быть общедоступными или защищенными, но не считаются разработчиками SDK.

Ищите другие решения по любой проблеме, которые вы испытываете.

+9

Хм, интересно! Поэтому перефразируем логическое обоснование: «Мы не могли потрудиться, чтобы разобраться в правильной инкапсуляции, поэтому мы подорвали язык». ... –

+0

Я заметил тег '{@hide}. Я предположил, что именно поэтому 'mScrollX' не появлялся в JavaDocs (например, [предлагаемый тег' @ exclude'] (http://java.sun.com/j2se/javadoc/proposed-tags.html), который отменяет ' @ hide'). Я не понимал, что SDK является заглушкой версии API. –

+0

Одна вещь, о которой я не могу понять, - это защищенная переменная класса ** View ** доступна в классе ** ScrollView **. Как это возможно ? Иерархия - ScrollView расширяет FramLayout расширяет ViewGroup расширяет представление. Итак, защищенная переменная класса View должна быть доступна только в ViewGroup. –

5

Это очень прямолинейно: обратите внимание на аннотацию @hide над этими переменными. Это аннотация для Android, которая скрывает поля/методы из общедоступного SDK. Вот почему вы не можете получить к ним доступ напрямую.

Romain Guy mentioned it in этот пост.

+0

это беспокоит. в чем смысл открытого источника? поэтому люди могут прочитать источник и понять, что происходит. но источник, выпущенный здесь, является поддельным? а не тот, который используется в производстве? это также приемлемо, * если прозрачный *.Мне все равно, является ли источник JDK * реальным *, но любая информация, полученная от его чтения, должна быть верной в реальной системе. – irreputable

+0

Вы должны понимать значение open-source. Прежде всего, вы можете создать свою собственную версию Android непосредственно из источника, внести любые изменения, которые вы хотите, и использовать каждый метод или поле, скрытые или нет. Это то, что делают производители телефонов, и некоторые пользовательские повара ROM в сообществе. Разработчики могут извлечь выгоду из другого аспекта Android, являющегося открытым исходным кодом, и который проходит через источник и понимает, как все работает за кулисами, для меня это так же важно, как и сама документация. – Lior

+2

Тот факт, что некоторые поля или методы скрыты, обычно является одним из следующих двух: 1. Они могут измениться в будущей версии SDK, поэтому они хотят уменьшить вероятность несовместимости приложений, что позволит вам, разработчику, много работа с вашими приложениями и 2. Использование этих полей непосредственно, как в вашем случае, может помешать правильной работе, как работа API внутри. – Lior

4

Вы можете попробовать установить поля с отражением:

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. 
} 

Заметим, однако, что вы полагаетесь на незарегистрированной и неподдерживаемый поведение, когда вы это делаете, и поэтому вы должны быть готовы к вещи, чтобы сломать на некоторых устройствах или в будущих версиях.