it-swarm.com.de

Wie lässt sich die log TAG-Konstante in Kotlin am besten definieren?

Ich erstelle meine ersten Kotlin-Klassen in meiner Android-Anwendung. Normalerweise habe ich zu Protokollierungszwecken eine Konstante mit dem Namen TAG. Was ich in Java machen würde, ist:

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

Ich weiß, dass ich in Kotlin-Klassen TAG folgendermaßen erstellen kann:

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

Dies ist in Ordnung für Projekte, die Java und Kotlin verwenden. Was ist, wenn ich ein neues Projekt starte, das nur in Kotlin ist? Wie kann ich dort TAG konstant definieren? Gibt es mehr Kotlin-Wege, wo ich diese seltsame Konstruktion class.Java.simpleName nicht habe?

26
Mario Kutlev

Im Allgemeinen sind Konstanten alle Großbuchstaben (zB FOO) und im Begleitobjekt

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

    }
}

und zum Definieren des TAG-Felds können Sie Folgendes verwenden:

private val TAG = MyClass::class.qualifiedName
24

Mit dieser Erweiterung können wir TAG in jeder Klasse verwenden

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

Es wurde auch als gültiges Android-Log-Tag validiert.

6
Fredy Mederos

In Kotlin können Sie eine Erweiterung erstellen und stattdessen einen Tag als Methodenaufruf aufrufen. Dies würde bedeuten, dass Sie es niemals innerhalb jeder Klasse definieren müssen. Wir können es bei jedem Aufruf der Methode dynamisch erstellen:

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

Einfach das Folgende zu machen, hat für mich funktioniert.

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

Ein allgemein empfohlener Ansatz für die Verwendung von companion object generiert eine zusätzliche static final-Instanz einer Begleiterklasse und ist daher hinsichtlich Leistung und Speicher schlecht.

Der beste Weg (IMHO)

Definieren Sie ein Protokolltag als eine Konstante der obersten Ebene. Daher wird nur eine zusätzliche Klasse generiert (MyClassKt). Im Vergleich zu companion object gibt es jedoch keine static final-Instanz (und keine Instanz).

private const val TAG = "MyLogTag"

class MyClass {

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

Andere Option

Verwenden Sie eine normale val. Das sieht zwar ungewöhnlich aus, wenn ein Protokolltag nicht als Konstante in Großbuchstaben betrachtet wird, dies generiert jedoch keine Klassen und hat den geringsten Overhead.

class MyClass {

    private val tag = "myLogTag"

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

Sie können Ihre TAG durch @JvmField wie folgt definieren:

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

Für weitere Details lesen Sie diesen Artikel: Kotlins versteckte Kosten

3
Andrew Wang

Ich habe einige Log-Erweiterungsfunktionen erstellt, um zu vermeiden, dass das Log-Tag wie in Java deklariert wird (möglicherweise weniger performant, aber angesichts der Tatsache, dass wir über Protokollierung sprechen, sollte dies IMO akzeptabel sein). Der Ansatz verwendet reified type-Parameter und andere Kotlin-Goodies, um den einfachen Namen der Klasse abzurufen. Hier ist ein grundlegendes Beispiel:

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

Sie finden eine ausführlichere Gist hier

2
Paolo

Antwort mit Kotlin 1.2.20 aktualisiert

class MyClass {
    companion object {

        @JvmField
        public val FOO = 1
    }
}

verwendet

MyClass.FOO
2
Kasim Rangwala

Ich habe einen Weg gefunden, der "copy-paste" -fähig ist, da Sie nicht den Namen Ihrer Klasse eingeben müssen:

package com.stackoverflow.mypackage

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

Es ist nicht die eleganteste Lösung, aber es funktioniert.

this::class.toString().split(".").last() gibt Ihnen "com.stackoverflow.mypackage.MyClass$Companion", so dass Sie dropLast(10) benötigen, um $Companion zu entfernen.

Alternativ können Sie dies tun:

package com.stackoverflow.mypackage

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

Dann ist die Variablenvariable TAG nicht mehr "statisch" und folgt nicht den empfohlenen Namenskonventionen.

1
jpihl

TAG-Variable mit val deklarieren 

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

Verwenden Sie die Variable gerne

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

In Android Studio ist es üblich, etwas umzubenennen, indem Sie mit der rechten Maustaste auf den Namen klicken und Refactor-> Umbenennen auswählen. Also, ich denke, es ist in Ordnung, so etwas zu tun,

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

wenn Sie die Klasse MyClass wie oben beschrieben umbenennen, schlägt die IDE vor, Ihren LOG_TAG-String ebenfalls umzubenennen. 

Letztlich gibt es Vor-und Nachteile dieser Methode gegenüber anderen Methoden. Da LOG_TAG ein String ist, müssen Sie kotlin-reflect.jar nicht importieren, wie Sie es tun würden, wenn Sie LOG_TAG gleich MyClass::class.simpleName setzen. Da die Variable mit dem Schlüsselwort const als Kompilierungszeitkonstante deklariert wird, ist der generierte Bytecode kleiner, da keine weiteren verborgenen Getter generiert werden müssen, wie in diesem Artikel beschrieben.

0
Max

AnkoLogger verwendet eine Schnittstelle, um den Protokolltag zu definieren.

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

Sie können es so verwenden:

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

Vielleicht kann AnkoLogger Ihnen einige Ideen geben, um ein benutzerdefiniertes Protokollierungswerkzeug zu implementieren.

0
Fredy Mederos

Ich erstelle die Konstante als Begleitobjekt:

companion object {
    val TAG = "SOME_TAG_VALUE"
}

Dann kann ich es so verwenden:

MyClass.TAG
0