Al crear una vista personalizada, me di cuenta de que muchas personas parecen hacerlo así:
public MyView(Context context) {
super(context);
// this constructor used when programmatically creating view
doAdditionalConstructorWork();
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
// this constructor used when creating view through XML
doAdditionalConstructorWork();
}
private void doAdditionalConstructorWork() {
// init variables etc.
}
Mi primera pregunta es, ¿qué pasa con el constructor MyView(Context context, AttributeSet attrs, int defStyle)
? No estoy seguro de dónde se usa, pero lo veo en la superclase. ¿Lo necesito y dónde se usa?
fuente
Si anula los tres constructores, NO HAGA
this(...)
LLAMADAS EN CASCADA . En su lugar, deberías estar haciendo esto:La razón es que la clase principal podría incluir atributos predeterminados en sus propios constructores que podría anular accidentalmente. Por ejemplo, este es el constructor de
TextView
:Si no llamó
super(context)
, no habría establecido correctamenteR.attr.textViewStyle
como el atributo de estilo.fuente
MyView (contexto contextual)
Se usa al instanciar Vistas mediante programación.
MyView (contexto de contexto, atributos de AttributeSet)
Usado por
LayoutInflater
para aplicar atributos xml. Si se nombra uno de estos atributosstyle
, los atributos se buscarán en el estilo antes de buscar valores explícitos en el archivo xml de diseño.MyView (contexto de contexto, AttributeSet attrs, int defStyleAttr)
Suponga que desea aplicar un estilo predeterminado a todos los widgets sin tener que especificar
style
en cada archivo de diseño. Por ejemplo, haga que todas las casillas de verificación sean rosas de forma predeterminada. Puede hacer esto con defStyleAttr y el marco buscará el estilo predeterminado en su tema.Tenga en cuenta que
defStyleAttr
se nombró incorrectamentedefStyle
hace algún tiempo y hay una discusión sobre si este constructor es realmente necesario o no. Ver https://code.google.com/p/android/issues/detail?id=12683MyView (Contexto contextual, AttributeSet attrs, int defStyleAttr, int defStyleRes)
El 3er constructor funciona bien si tiene control sobre el tema base de las aplicaciones. Eso está funcionando para Google porque envían sus widgets junto con los Temas predeterminados. Pero suponga que está escribiendo una biblioteca de widgets y desea establecer un estilo predeterminado sin que sus usuarios necesiten modificar su tema. Ahora puede hacer esto mediante el
defStyleRes
establecimiento del valor predeterminado en los 2 primeros constructores:Considerándolo todo
Si está implementando sus propias vistas, solo los 2 primeros constructores deberían ser necesarios y el marco puede invocarlos.
Si desea que sus Vistas sean extensibles, puede implementar el cuarto constructor para que los niños de su clase puedan usar un estilo global.
No veo un caso de uso real para el 3er constructor. Tal vez sea un acceso directo si no proporciona un estilo predeterminado para su widget pero aún desea que sus usuarios puedan hacerlo. No debería pasar tanto.
fuente
Kotlin parece eliminar mucho de este dolor:
@JvmOverloads generará todos los constructores necesarios (consulte la documentación de esa anotación ), cada uno de los cuales presumiblemente llama super (). Luego, simplemente reemplace su método de inicialización con un bloque Kotlin init {}. ¡Se acabó el código repetitivo!
fuente
El tercer constructor es mucho más complicado. Déjenme tener un ejemplo.
El
SwitchCompact
paquete Support-v7 admitethumbTint
ytrackTint
atribuye desde la versión 24, mientras que la versión 23 no los admite. ¿Ahora desea admitirlos en la versión 23 y cómo lo hará para lograrlo?Suponemos utilizar encargo Ver
SupportedSwitchCompact
extiendeSwitchCompact
.Es un estilo de código tradicional. Tenga en cuenta que pasamos 0 al tercer parámetro aquí . Cuando ejecute el código,
getThumbDrawable()
siempre encontrará que devuelve nulo lo extraño que es porque el métodogetThumbDrawable()
es el método de su superclaseSwitchCompact
.Si pasas
R.attr.switchStyle
al tercer parámetro, todo va bien. Entonces, ¿por qué?El tercer parámetro es un atributo simple. El atributo apunta a un recurso de estilo. En el caso anterior, el sistema encontrará el
switchStyle
atributo en el tema actual, afortunadamente el sistema lo encuentra.En
frameworks/base/core/res/res/values/themes.xml
, verá:fuente
Si tiene que incluir tres constructores como el que se está discutiendo ahora, también podría hacerlo.
fuente