web-dev-qa-db-fra.com

Quel est le meilleur moyen de définir la constante de log TAG dans Kotlin?

Je crée mes premières classes de Kotlin dans mon application Android. Habituellement, à des fins de journalisation, j'ai une constante portant le nom TAG. Ce que je ferais en Java, c'est:

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

Je sais que dans les classes Kotlin, je peux créer TAG de cette façon:

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

Cela convient aux projets utilisant Java et Kotlin, mais que se passe-t-il si je lance un nouveau projet uniquement dans Kotlin? Comment puis-je définir là TAG constante? Y a-t-il plus de manière Kotlin où je n'ai pas cette construction class.Java.simpleName étrange?

26
Mario Kutlev

En général, les constantes sont toutes en majuscules (ex. FOO) et situées dans le objet compagnon :

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

    }
}

et pour définir le champ TAG, vous pouvez utiliser:

private val TAG = MyClass::class.qualifiedName
24
Gabriele Mariotti

Cette extension nous permet d’utiliser TAG dans n’importe quelle classe

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")

Il a également validé pour fonctionner comme une balise de journal valide Android.

6
Fredy Mederos

Dans Kotlin, vous pouvez créer une extension et appeler tag en tant qu'appel de méthode. Cela signifierait que vous n'auriez jamais à le définir à l'intérieur de chaque classe, nous pouvons le construire dynamiquement chaque fois que nous appelons la méthode:

inline fun <reified T> T.TAG(): String = T::class.Java.simpleName
5
user8159708

Faire simplement ce qui suit a fonctionné pour moi.

private val TAG = this::class.Java.simpleName
5
nickgzzjr

L’approche généralement suggérée d’utiliser le companion object génère une instance supplémentaire de static final d’une classe compagnon, ce qui nuit aux performances et à la mémoire.

Le meilleur moyen (IMHO)

Définissez une balise de journal comme une constante de niveau supérieur. Ainsi, seule une classe supplémentaire est générée (MyClassKt). Toutefois, par rapport à companion object, il n'y aura pas d'instance static final (et aucune instance que ce soit):

private const val TAG = "MyLogTag"

class MyClass {

    fun logMe() {
        Log.w(TAG, "Message")
    }
}

Une autre option

Utilisez une val normale. Bien que cela semble inhabituel de voir une balise de journal pas comme une constante majuscule, cela ne générera aucune classe et entraînera un minimum de temps système.

class MyClass {

    private val tag = "myLogTag"

    fun logMe() {
        Log.w(tag, "Message")
    }
}
4
Yaroslav Mytkalyk

Vous pouvez définir votre TAG par @JvmField comme ci-dessous:

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

Pour plus de détails, vous pouvez lire cet article: Les coûts cachés de Kotlin

3
Andrew Wang

J'ai créé certaines fonctions d'extension de journal pour éviter de déclarer la balise de journal comme nous le faisions en Java (peut-être moins performant, mais étant donné que nous parlons de journalisation, cela devrait être un IMO acceptable). Cette approche utilise des paramètres de type réifiés et d’autres goodies Kotlin pour récupérer le nom simple de la classe. Voici un exemple de base:

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

Vous pouvez trouver un Gist plus élaboré ici

2
Paolo

Réponse mise à jour avec Kotlin 1.2.20

class MyClass {
    companion object {

        @JvmField
        public val FOO = 1
    }
}

les usages

MyClass.FOO
2
Kasim Rangwala

J'ai trouvé un moyen qui est plus "copier-coller", puisqu'il ne vous oblige pas à taper le nom de votre classe:

package com.stackoverflow.mypackage

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

Ce n'est pas la solution la plus élégante mais ça marche.

this::class.toString().split(".").last() vous donnera "com.stackoverflow.mypackage.MyClass$Companion" donc vous avez besoin de la dropLast(10) pour supprimer $Companion.

Sinon, vous pouvez le faire:

package com.stackoverflow.mypackage

class MyClass
{
    val TAG = this::class.simpleName
}

Mais alors la variable membre TAG n'est plus "statique" et ne respecte pas les conventions de dénomination recommandées.

1
jpihl

Déclarez la variable TAG avec 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
   }
}

Utilisez la variable comme

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

Dans Android Studio, la méthode habituelle pour renommer un élément consiste à cliquer avec le bouton droit de la souris sur le nom, sélectionnez Refactor> Renommer. Donc, je pense que c'est bien de faire quelque chose comme ça,

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

car si vous renommez la classe MyClass comme je l'ai décrit, alors IDE suggérera de renommer également votre chaîne LOG_TAG. 

En fin de compte, il y a des avantages et des inconvénients à utiliser cette méthode par rapport à d'autres méthodes. LOG_TAG étant une chaîne, il n'est pas nécessaire d'importer le fichier kotlin-reflect.jar, comme vous le feriez si vous définissez LOG_TAG égal à MyClass::class.simpleName. De plus, comme la variable est déclarée comme une constante de compilation avec le mot clé const, le bytecode généré est plus petit puisqu'il n'est pas nécessaire de générer plus de getters cachés, comme décrit dans cet article .

0
Max

AnkoLogger utilise une interface pour définir la balise de journal.

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")
    }
}

Vous pouvez l'utiliser comme ceci:

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

Peut-être qu'AnkoLogger peut vous donner quelques idées pour implémenter un outil de journalisation personnalisé.

0
Fredy Mederos

Je crée la constante en tant qu'objet compagnon:

companion object {
    val TAG = "SOME_TAG_VALUE"
}

Ensuite, je peux l'utiliser comme ça:

MyClass.TAG
0
Matias Elorriaga