variable estatica constantes constante constant companion java android kotlin constants

java - estatica - ¿Cuál es la mejor manera de definir la constante TAG log en Kotlin?



set kotlin (13)

Estoy creando mis primeras clases de Kotlin en mi aplicación de Android. Por lo general, para fines de registro tengo una constante con el nombre TAG . Lo que haría en Java es:

private static final String TAG = MyClass.class.getSimpleName();

Sé que en las clases de Kotlin puedo crear TAG esta manera:

private val TAG = MyClass::class.java.simpleName

Esto está bien para los proyectos que usan Java y Kotlin, pero ¿qué sucede si comienzo un nuevo proyecto que solo está en Kotlin? ¿Cómo puedo definir la constante TAG ? ¿Hay alguna forma de Kotlin en la que no tenga esta extraña construcción class.java.simpleName ?


Creé algunas funciones de extensión de registro para evitar declarar la etiqueta de registro como hicimos en Java (tal vez con menos rendimiento, pero dado que estamos hablando de registro, esto debería ser una OMI aceptable). El enfoque utiliza parámetros de tipo reificado y otras golosinas de Kotlin para recuperar el nombre simple de la clase. Aquí hay un ejemplo básico:

inline fun <reified T> T.logi(message: String) = Log.i(T::class.java.simpleName, message)

Puedes encontrar una esencia más elaborada here


Declaración de variable TAG con val

class YourClass { companion object { //if use java and kotlin both in project //private val TAG = MyClass::class.java.simpleName //if use only kotlin in project private val TAG = YourClass::class.simpleName } }

Usa la variable como

Log.d(YourClass.TAG, "Your message"); //or Log.e(TAG, "Your message");


El enfoque comúnmente sugerido para usar el companion object genera una instancia static final extra static final de una clase compañera y, por lo tanto, es un mal rendimiento y memoria.

La mejor manera (IMHO)

Defina una etiqueta de registro como una constante de nivel superior, por lo tanto, solo se genera una clase extra ( MyClassKt ), pero en comparación con el companion object no habrá una instancia static final de ella (y ninguna instancia en absoluto):

private const val TAG = "MyLogTag" class MyClass { fun logMe() { Log.w(TAG, "Message") } }

Otra opción

Utilice un valor normal. Aunque esto parece inusual para ver una etiqueta de registro no como una constante en mayúsculas, no generará ninguna clase y tiene menos sobrecarga.

class MyClass { private val tag = "myLogTag" fun logMe() { Log.w(tag, "Message") } }


En Android Studio, la forma habitual de renombrar algo es hacer clic derecho en el nombre, seleccione Refactor-> Renombrar. Entonces, creo que está bien hacer algo como esto,

class MyClass { companion object { private const LOG_TAG = "MyClass" } }

porque si cambia el nombre de la clase MyClass como describí, entonces el IDE sugerirá cambiar el nombre de su cadena LOG_TAG también.

En última instancia, hay ventajas y desventajas de usar este método en comparación con otros métodos. Debido a que LOG_TAG es una cadena, no es necesario importar el archivo kotlin-reflect.jar, como lo haría si configurara LOG_TAG igual a MyClass::class.simpleName . Además, como la variable se declara como una constante de tiempo de compilación con la palabra clave const , el bytecode generado es más pequeño, ya que no necesita generar más captadores ocultos, como se describe en este artículo .


En Kotlin podría crear una extensión, y llamar a la etiqueta como una llamada a un método. Esto significaría que nunca tendría que definirlo dentro de cada clase, podemos construirlo dinámicamente cada vez que llamemos el método:

inline fun <reified T> T.TAG(): String = T::class.java.simpleName


En general, las constantes son todas mayúsculas (por ejemplo, FOO) y están ubicadas en el objeto compañero :

class MyClass { companion object { public const val FOO = 1 } }

y para definir el campo TAG puedes usar:

private val TAG = MyClass::class.qualifiedName


Encontré una forma que es más fácil de "copiar y pegar", ya que no requiere que escribas el nombre de tu clase:

package com..mypackage class MyClass { companion object { val TAG = this::class.toString().split(".").last().dropLast(10) } }

No es la solución más elegante pero funciona.

this::class.toString().split(".").last() le dará "com..mypackage.MyClass$Companion" por lo que necesita el dropLast(10) para eliminar $Companion .

Alternativamente puedes hacer esto:

package com..mypackage class MyClass { val TAG = this::class.simpleName }

Pero entonces la variable miembro TAG ya no es "estática" y no sigue las convenciones de nomenclatura recomendadas.


Esta extensión nos permite utilizar TAG en cualquier clase.

val Any.TAG: String get() { val tag = javaClass.simpleName return if (tag.length <= 23) tag else tag.substring(0, 23) } //usage Log.e(TAG,"some value")

También se validó para funcionar como una etiqueta de registro válida para Android.


Estoy creando la constante como un objeto compañero:

companion object { val TAG = "SOME_TAG_VALUE" }

Entonces, puedo usarlo así:

MyClass.TAG


Puede definir su TAG por @JvmField siguiente manera:

companion object { @JvmField val TAG: String = MyClass::class.java.simpleName }

Para más detalles, puedes leer este artículo: costos ocultos de Kotlin


Respuesta actualizada con Kotlin 1.2.20

class MyClass { companion object { @JvmField public val FOO = 1 } }

usos

MyClass.FOO


Simplemente haciendo lo siguiente funcionó para mí.

private val TAG = this::class.java.simpleName


AnkoLogger utiliza una interfaz para definir la etiqueta de registro.

interface AnkoLogger { /** * The logger tag used in extension functions for the [AnkoLogger]. * Note that the tag length should not be more than 23 symbols. */ val loggerTag: String get() = getTag(javaClass) } private fun getTag(clazz: Class<*>): String { val tag = clazz.simpleName return if (tag.length <= 23) { tag } else { tag.substring(0, 23) } } inline fun AnkoLogger.info(message: () -> Any?) { val tag = loggerTag if (Log.isLoggable(tag, Log.INFO)) { Log.i(tag, message()?.toString() ?: "null") } }

Puedes usarlo así:

class MyClass : AnkoLogger { fun someFun(){ info("logging info") } }

Quizás AnkoLogger pueda darle algunas ideas para implementar una herramienta de registro personalizada.