2011-02-06 10 views
15

Estoy escribiendo una vista personalizada que extiende directamente android.view.View. Si intento acceder a los campos mScrollX o mScrollY, veo un error que indica que el campo "no se puede resolver o no es un campo". El source code for android.view.View tiene mScrollX, mScrollY y variables similares declaradas protected. ¿Cómo es que mi subclase directa no puede acceder a los campos protegidos de su clase principal? (Las clases como ScrollView aparentemente pueden).Campos protegidos no visibles para las subclases

P.S. Me doy cuenta de que puedo llamar al getScrollX(), pero quiero actualizar estos campos; llamar al setScroll() tiene efectos secundarios que no quiero.

+0

Las subclases raras, incluso estando en otros paquetes, pueden acceder a las variables protegidas de su superclase. Supongo que estás usando la versión incorrecta. ¿Puedes mostrar algo de tu código? –

+0

Comportamiento confirmado. –

Respuesta

20

Se debe a que no forman parte del SDK de Android.

Aquí está el código fuente para mScrollX:

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

Usted notará la anotación @hide. Eso significa que esto no es parte del SDK de Android. La parte del proceso de compilación que crea el SDK de Android no incluirá este miembro de datos en la edición del apéndice android.view.View que se encuentra en el archivo android.jar contra el que está compilando.

La anotación @hide se utiliza para cosas que para fines internos deben ser públicas o estar protegidas, pero no se consideran algo que los desarrolladores de SDK deberían estar usando.

Encuentre otras soluciones para cualquier problema que tenga.

+9

Hmm, ¡interesante! Así que para parafrasear el razonamiento: "No podíamos molestarnos en ordenar la encapsulación adecuada, así que subvertimos el lenguaje". ... –

+0

Me di cuenta de la etiqueta '{@hide}'. Supuse que era por eso que 'mScrollX' no apareció en los JavaDocs (como la [propuesta de etiqueta @ @ exclude'] (http://java.sun.com/j2se/javadoc/proposed-tags.html), que reemplaza' @ hide'). No me di cuenta de que el SDK era una versión parcial de la API. –

+0

Una cosa que no puedo entender es que se accede a la variable protegida de la clase ** Vista ** en la clase ** ScrollView **. Cómo es esto posible ? La jerarquía es - ScrollView extiende FramLayout extiende ViewGroup extends View. Por lo tanto, la variable protegida de la clase View solo debería ser accesible en ViewGroup. –

5

Es muy directo: observe la @hide anotación sobre estas variables. Es una anotación específica de Android que oculta los campos/métodos del SDK público. Es por eso que no puedes acceder a ellos directamente.

Romain Guy mentioned it in esta publicación.

+0

que es perturbador. ¿Cuál es el punto de la fuente abierta? para que la gente pueda leer la fuente y entender lo que está pasando. pero la fuente publicada aquí es falsa? no el utilizado en la producción? eso también es aceptable, * si es transparente *.No me importa si la fuente JDK es * real *, pero cualquier información que obtuve de la lectura debe ser cierta en el sistema real. – irreputable

+0

Tienes que entender el significado de código abierto. En primer lugar, puede crear su propia versión de Android directamente desde la fuente, hacer las modificaciones que desee y utilizar cada método o campo, ya sea que esté oculto o no. Eso es lo que hacen los fabricantes de teléfonos y algunos de los cocineros ROM personalizados en la comunidad. Los desarrolladores pueden beneficiarse de otro aspecto de que Android es de código abierto, y que está pasando por la fuente y comprender cómo funcionan las cosas detrás de escena, para mí esto es tan importante como la documentación en sí misma. – Lior

+2

El hecho de que algunos campos o métodos estén ocultos suele ser uno de los siguientes: 1. Pueden cambiar en la versión futura del SDK, por lo que quieren reducir las posibilidades de incompatibilidad de aplicaciones, lo que le ahorra a usted, al desarrollador una gran cantidad de trabaje manteniendo sus aplicaciones, y 2. Usar estos campos directamente como en su caso podría interferir con el trabajo apropiado de cómo funciona la API internamente. – Lior

4

Usted podría tratar de establecer los campos con la reflexión:

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

Tenga en cuenta, sin embargo, que usted está confiando en el comportamiento indocumentado y sin apoyo cuando se hace esto, y lo que debe estar preparado para las cosas para romper en algunos dispositivos o en versiones futuras.

Cuestiones relacionadas