State<List<User>?> ist kein Delegat: Top 3 Fehler und Lösungen in Kotlin

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Stille Panik: Wenn Kotlin schreit, dass State kein Delegat sein kann

\n\n

Sie schreiben Code in Kotlin, verwenden Jetpack Compose, alles läuft nach Plan. Und plötzlich – peng! – gibt der Compiler eine Meldung aus, bei der Anfängern das Blut in den Adern gefriert: Type 'State<List<User>?>' has no method 'getValue(Nothing?, KProperty<*>)' and thus it cannot serve as a delegate. Das klingt wie ein Todesurteil, ist aber in Wirklichkeit nur ein Hilferuf Ihres Codes. Lassen Sie uns verstehen, was er sagen will und wie Sie sich mit ihm anfreunden können.

\n\n

Dieser Fehler ist einer der beliebtesten auf Stack Overflow (tausende Aufrufe!) und verfolgt Entwickler, die gerade erst beginnen, delegierte Eigenschaften in Kotlin zu meistern. In diesem Artikel übersetzen wir nicht nur die Fehlermeldung, sondern zeigen drei reale Situationen, in denen sie auftritt, und geben funktionierende Lösungen. Sie erfahren, wie Sie StateFlow in Compose richtig verwenden, wie Sie sich in Kotlin-Delegaten nicht verirren und warum LiveData sich manchmal anders verhält als erwartet.

\n\n

Was ist ein Delegat in Kotlin und warum wird State keiner?

\n\n

Zunächst – eine kurze Einführung. Delegierte Eigenschaften in Kotlin (Schlüsselwort by) ermöglichen es, die Logik von Getter und Setter in ein separates Objekt auszulagern. Zum Beispiel:

\n\n
var name: String by Delegates.observable("") { prop, old, new ->\n    println("$old → $new")\n}\n
\n\n

Damit ein Objekt ein Delegat sein kann, muss es die Methoden getValue() und ggf. setValue() mit einer bestimmten Signatur implementieren. Der Fehler Type 'State<List<User>?>' has no method 'getValue(Nothing?, KProperty<*>)' besagt genau dies: Ihr Objekt vom Typ State<List<User>?> hat keine passende getValue-Methode. Der Compiler kann es nicht als Delegaten verwenden.

\n\n

Kommen wir nun zu drei konkreten Szenarien, in denen dieser Fehler am häufigsten auftritt.

\n\n

Fehler 1: Verwechslung von by und Zuweisung von StateFlow

\n\n

Der häufigste Fall – wenn ein Entwickler versucht, by zur Zuweisung von StateFlow in einer ViewModel zu verwenden, dies aber falsch macht. Sehen Sie sich diesen Code an:

\n\n
// ❌ Fehler! So darf man es nicht machen\nclass MyViewModel : ViewModel() {\n    private val _users = MutableStateFlow<List<User>?>(null)\n    val users: StateFlow<List<User>?> by _users  // Fehler!\n}\n
\n\n

Hier ist _users ein MutableStateFlow, und wir versuchen, ihn zum Delegaten für die Eigenschaft users zu machen. Aber StateFlow implementiert getValue für Kotlin-Eigenschaften nicht. Es ist kein Delegat, sondern ein reaktiver Stream.

\n\n

Lösung: Verwenden Sie asStateFlow()

\n\n

Der richtige Weg ist nicht zu delegieren, sondern zu konvertieren:

\n\n
// ✅ Richtig\nclass MyViewModel : ViewModel() {\n    private val _users = MutableStateFlow<List<User>?>(null)\n    val users: StateFlow<List<User>?> = _users.asStateFlow()\n}\n
\n\n

Die Methode asStateFlow() erstellt eine unveränderliche Kopie, die sicher nach außen gegeben werden kann. Keine Delegaten, keine Fehler.

\n\n

Fehler 2: Verwendung von by mit LiveData in Compose

\n\n

Die zweithäufigste Situation – der Versuch, LiveData direkt mit by in Jetpack Compose zu verwenden. Entwickler, die aus der Welt der View-Systeme kommen, sind an LiveData gewöhnt und versuchen, denselben Ansatz anzuwenden:

\n\n
// ❌ Fehler!\n@Composable\nfun UserList(viewModel: MyViewModel) {\n    val users: List<User>? by viewModel.users  // Fehler!\n    // ...\n}\n
\n\n

Hier hat viewModel.users den Typ LiveData<List<User>?>. Und LiveData ist kein Delegat für Compose-Eigenschaften. Der Compiler gibt erneut denselben Fehler aus: Type 'LiveData<List<User>?>' has

Blogs

Buchempfehlungen