Thierry  Perret

Thierry Perret

1660726141

initialisation Des Variables Lazy Et Lateinit Dans Kotlin

Kotlin nous oblige généralement à initialiser les propriétés dès que nous les définissons. Cela semble étrange lorsque nous ne connaissons pas la valeur initiale idéale, en particulier dans le cas des propriétés Android axées sur le cycle de vie.

Heureusement, il existe un moyen de résoudre ce problème. L'éditeur IntelliJ IDEA vous avertira si vous déclarez une propriété de classe sans l'initialiser et vous recommandera d'ajouter un mot- lateinitclé.

Que se passe-t-il si une propriété ou un objet initialisé n'est pas réellement utilisé dans le programme ? Eh bien, ces initialisations inutilisées seront un passif pour le programme puisque la création d'objets est un processus lourd. Ceci est un autre exemple d'où lateinitpeut venir à notre secours.

Cet article explique comment le lateinitmodificateur et la délégation paresseuse peuvent prendre en charge les initialisations précoces inutilisées ou inutiles. Cela rendra votre flux de travail de développement Kotlin plus efficace.

lateinità Kotlin

Le lateinitmot-clé signifie « initialisation tardive ». Lorsqu'il est utilisé avec une propriété de classe, le lateinitmodificateur empêche la propriété d'être initialisée au moment de la construction de l'objet de sa classe.

La mémoire est allouée aux lateinitvariables uniquement lorsqu'elles sont initialisées plus tard dans le programme, plutôt qu'au moment de leur déclaration. C'est très pratique en terme de souplesse d'initialisation.

Regardons quelques fonctionnalités importantes qui lateinita à offrir!

Principales caractéristiques

Premièrement, la mémoire n'est pas allouée à une lateinitpropriété au moment de la déclaration. L'initialisation a lieu plus tard quand bon vous semble.

Une lateinitpropriété peut changer plus d'une fois tout au long du programme et est censée être modifiable. C'est pourquoi vous devez toujours le déclarer comme a varet non comme a valou const.

L' lateinitinitialisation peut vous éviter des vérifications null répétitives dont vous pourriez avoir besoin lors de l'initialisation de propriétés en tant que types nullables. Cette fonctionnalité des lateinitpropriétés ne prend pas en charge le type nullable.

En développant mon dernier point, lateinitpeut être bien utilisé avec des types de données non primitifs. Cela ne fonctionne pas avec les types primitifs comme longou int. En effet, chaque fois qu'une lateinitpropriété est accessible, Kotlin lui fournit une valeur nulle sous le capot pour indiquer que la propriété n'a pas encore été initialisée.

Les types primitifs ne peuvent pas être null, il n'y a donc aucun moyen d'indiquer une propriété non initialisée. En conséquence, les types primitifs lèvent une exception lorsqu'ils sont utilisés avec le lateinitmot clé.

Enfin, une lateinitpropriété doit être initialisée à un moment donné avant d'y accéder, sinon elle générera une UninitializedPropertyAccessExceptionerreur, comme indiqué ci-dessous :

Erreur d'exception d'accès à la propriété non initialisée

Une lateinitpropriété accédée avant l'initialisation conduit à cette exception.

Kotlin permet de vérifier si une lateinitpropriété est initialisée. Cela peut être pratique pour gérer l'exception de désinitialisation dont nous venons de parler.

lateinit var myLateInitVar: String
...

if(::myLateInitVar.isInitialized) {
  // Do something
}

Exemples de lateinitmodificateurs utilisés

Voyons le lateinitmodificateur en action avec un exemple simple. Le code ci-dessous définit une classe et initialise certaines de ses propriétés avec des valeurs factices et nulles.

class TwoRandomFruits {
  var fruit1: String = "tomato" 
  var fruit2: String? = null


  fun randomizeMyFruits() {
      fruit1 = randomFruits()
      fruit2 = possiblyNullRandomFruits()
  }


  fun randomFruits(): String { ... }
  fun possiblyNullRandomFruits(): String? { ... }
}

fun main() {
    val rf= RandomFruits()
    rf.randomizeMyFruits()


    println(rf.fruit1.capitalize())
    println(rf.fruit2?.capitalize()) // Null-check
}

Ce n'est pas la meilleure façon d'initialiser une variable, mais dans ce cas, cela fait toujours le travail.

Comme vous pouvez le voir ci-dessus, si vous choisissez de rendre la propriété nullable, vous devrez la vérifier à chaque fois que vous la modifiez ou l'utilisez. Cela peut être assez fastidieux et ennuyeux.

Abordons ce problème avec le lateinitmodificateur :

class TwoRandomFruits {
  lateinit var fruit1: String // No initial dummy value needed
  lateinit var fruit2: String // Nullable type isn't supported here


  fun randomizeMyFruits() {
      fruit1 = randomFruits()
      fruit2 = when {
          possiblyNullRandomFruits() == null -> "Tomato" // Handling null values
          else -> possiblyNullRandomFruits()!!
      }
  }


  fun randomFruits(): String { ... }
  fun possiblyNullRandomFruits(): String? { ... }
}

fun main() {
    val rf= RandomFruits()
    rf.randomizeMyFruits()


    println(rf.fruit1.capitalize())
    println(rf.fruit2.capitalize())
}

Vous pouvez voir ce code en action ici .

La lateinitmise en œuvre parle d'elle-même et démontre une manière astucieuse de gérer les variables ! Outre le comportement par défaut de lateinit, le principal point à retenir ici est la facilité avec laquelle nous pouvons éviter d'utiliser le type nullable.

Propriétés axées sur le cycle de vie etlateinit

La liaison de données est un autre exemple d'utilisationlateinit pour initialiser une activité ultérieurement. Les développeurs souhaitent souvent initialiser la variable de liaison plus tôt pour l'utiliser comme référence dans d'autres méthodes pour accéder à différentes vues.

Dans la MainActivityclasse ci-dessous, nous avons déclaré la liaison avec le lateinitmodificateur pour obtenir la même chose.

package com.test.lateinit

import androidx.appcompat.app.AppCompatActivity
import ...

class MainActivity : AppCompatActivity() {
  lateinit var binding: ActivityMainBinding

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = DataBindingUtil.setContentView(this, R.layout.activity_main)

    ...
  }
  ...
}

La liaison pour MainActivityne peut être initialisée qu'une fois que la fonction de cycle de vie de l'activité, onCreate(), est déclenchée. Par conséquent, déclarer la liaison avec le lateinitmodificateur prend tout son sens ici.

Quand utiliserlateinit

Avec l'initialisation de variable régulière, vous devez ajouter une valeur fictive et, très probablement, une valeur nulle. Cela ajoutera beaucoup de vérifications nulles chaque fois qu'elles seront consultées.

// Traditional initialization
var name: String? = null
...    
name = getDataFromSomeAPI()
...
// A null-check will be required whenever `name` is accessed.
name?.let { it-> 
  println(it.uppercase())
}

// Lateinit initialization
lateinit var name: String
...
name = getDatafromSomeAPI()
...
println(name.uppercase())

Nous pouvons utiliser le lateinitmodificateur pour éviter ces vérifications nulles répétées, en particulier lorsqu'une propriété est susceptible de fluctuer fréquemment.

Choses à retenir lors de l'utilisationlateinit

Il est bon de se rappeler de toujours initialiser une lateinitpropriété avant d'y accéder, sinon, vous verrez une grosse exception levée au moment de la compilation.

Assurez-vous également de conserver la propriété modifiable en utilisant une vardéclaration. Utiliser valet constn'aura aucun sens, car ils indiquent des propriétés immuables avec lesquelles lateinitne fonctionneront pas.

Enfin, évitez d'utiliser lateinitlorsque le type de données de la propriété donnée est primitif ou que les chances d'une valeur nulle sont élevées. Il n'est pas conçu pour ces cas et ne prend pas en charge les types primitifs ou nullables.

Délégation paresseuse à Kotlin

Comme son nom l'indique, lazyKotlin initialise une propriété de manière paresseuse. Essentiellement, il crée une référence mais ne va pour l'initialisation que lorsque la propriété est utilisée ou appelée pour la première fois.

Maintenant, vous vous demandez peut-être en quoi cela diffère de l'initialisation régulière. Eh bien, au moment de la construction d'un objet de classe, toutes ses propriétés publiques et privées sont initialisées dans son constructeur. Il y a une surcharge associée à l'initialisation des variables dans une classe ; plus il y a de variables, plus la surcharge sera importante.

Comprenons-le avec un exemple:

class X {
  fun doThis() {}
}

class Y {
  val shouldIdoThis: Boolean = SomeAPI.guide()
  val x = X()

  if(shouldIdoThis) {
    x.doThis()
  }
  ...
}

Bien qu'il ne l'utilise pas, class Ydans le code ci-dessus a toujours un objet créé de class X. La classe Xralentira également Ys'il s'agit d'une classe fortement construite.

La création d'objets inutiles est inefficace et peut ralentir la classe en cours. Il se peut que certaines propriétés ou certains objets ne soient pas requis dans certaines conditions, selon le déroulement du programme.

Il se peut également que des propriétés ou des objets reposent sur d'autres propriétés ou objets pour la création. La délégation paresseuse traite efficacement ces deux possibilités.

Principales caractéristiques

Une variable avec une initialisation différée ne sera pas initialisée tant qu'elle n'aura pas été appelée ou utilisée. De cette façon, la variable n'est initialisée qu'une seule fois, puis sa valeur est mise en cache pour une utilisation ultérieure dans le programme.

Puisqu'une propriété initialisée avec la délégation différée est censée utiliser la même valeur partout, elle est de nature immuable et est généralement utilisée pour les propriétés en lecture seule. Vous devez le marquer d'une valdéclaration.

Il est thread-safe, c'est-à-dire calculé une seule fois et partagé par tous les threads par défaut. Une fois initialisé, il se souvient ou met en cache la valeur initialisée tout au long du programme.

Contrairement à lateinit, la délégation différée prend en charge un setter et un getter personnalisés qui lui permettent d'effectuer des opérations intermédiaires lors de la lecture et de l'écriture de la valeur.

Exemple de délégation paresseuse en cours d'utilisation

Le code ci-dessous implémente des calculs simples pour calculer les aires de certaines formes. Dans le cas d'un cercle, le calcul nécessiterait une valeur constante pour pi.

class Area {
  val pi: Float = 3.14f


  fun circle(radius: Int): Float = pi * radius * radius
  fun rectangle(length: Int, breadth: Int = length): Int = length * breadth
  fun triangle(base: Int, height: Int): Float = base * height * .5f
}

fun main() {
  val area = Area()
  val squareSideLength = 51


  println("Area of our rectangle is ${area.rectangle(squareSideLength)}")
}

Comme vous pouvez le voir ci-dessus, aucun calcul de l'aire d'un cercle n'a été effectué, ce qui rend notre définition de piinutile. La propriété piest toujours initialisée et allouée de la mémoire.

Corrigeons ce problème avec la délégation paresseuse :

class Area {
  val pi: Float by lazy {
    3.14f
  } 


  fun circle(...) = ...
  fun rectangle(...) = ...
  fun triangle(...) = ...
}

fun main() {
  val area = Area()
  val squareSideLength = 51
  val circleRadius = 37

  println("Area of our rectangle is ${area.rectangle(squareSideLength)}")
  println("Area of our circle is ${area.circle(circleRadius)}")
}

Vous pouvez voir une démo de l'exemple ci-dessus ici .

L'implémentation ci-dessus de la délégation paresseuse n'est utilisée pique lorsqu'elle est accessible. Une fois accessible, sa valeur est mise en cache et réservée pour être utilisée tout au long du programme. Nous le verrons en action avec des objets dans les exemples suivants.

Actions intermédiaires

Voici comment vous pouvez ajouter des actions intermédiaires lors de l'écriture de valeurs via la délégation paresseuse. Le code ci-dessous lazyinitialise a TextViewdans une activité Android.

Chaque fois que cela TextViewest appelé pour la première fois dans le MainActivity, un message de débogage avec une LazyInitbalise sera enregistré, comme indiqué ci-dessous dans la fonction lambda du délégué :

...
class MainActivity : AppCompatActivity() {
  override fun onCreate(...) {
    ...  
    val sampleTextView: TextView by lazy {
      Log.d("LazyInit", "sampleTextView")
      findViewById(R.id.sampleTextView)
    }
  }
  ...
}

Délégation paresseuse dans les applications Android

Passons maintenant à l'application de la délégation paresseuse dans les applications Android. Le cas d'utilisation le plus simple peut être notre exemple précédent d'une activité Android qui utilise et manipule une vue de manière conditionnelle.

package com.test.lazy

import androidx.appcompat.app.AppCompatActivity
import ...

class MainActivity : AppCompatActivity() {
  lateinit var binding: ActivityMainBinding

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = DataBindingUtil.setContentView(this, R.layout.activity_main)


    val sharedPrefs by lazy {
      activity?
        .getPreferences(Context.MODE_PRIVATE)
    } 


    val startButton by lazy {
      binding.startButton
    }


    if(sharedPrefs.getBoolean("firstUse", true)) {
      startButton.isVisible = true
      startButton.setOnClickListener {
        // Finish onboarding, move to main screen; something like that
        sharedPrefs.setBoolean("firstUse", false)
      }
    }

  }
}

Ci-dessus, nous avons initialisé the SharedPreferenceset a Buttonavec une délégation paresseuse. La logique implique la mise en œuvre d'un écran d'intégration basé sur une valeur booléenne extraite des préférences partagées.

La différence entre by lazyet= lazy

L' by lazyinstruction ajoute une amélioration par le délégué paresseux directement à une propriété donnée. Son initialisation ne se fera qu'une seule fois lors de son premier accès.

val prop by lazy {
  ...
}

D'autre part, l' = lazyinstruction contient à la place une référence à l'objet délégué, par lequel vous pouvez utiliser la isInitialized()méthode de délégation ou y accéder avec la valuepropriété.

val prop = lazy {
  ...
}
...

if(prop.isInitialized()) {
  println(prop.value)
}

Vous pouvez voir une démo rapide du code ci-dessus ici.

Quand utiliserlazy

Envisagez d'utiliser des délégués paresseux pour alléger une classe qui implique des créations multiples et/ou conditionnelles d'autres objets de classe. Si la création d'objet dépend d'une propriété interne de la classe, la délégation paresseuse est la solution.

class Employee {
    ...
    fun showDetails(id: Int): List<Any> {
        val employeeRecords by lazy {
            EmployeeRecords(id) // Object's dependency on an internal property
        }
    }
    ...
}

Choses à retenir lors de l'utilisationlazy

L'initialisation différée est une délégation qui initialise quelque chose une seule fois et uniquement lorsqu'il est appelé. Il est destiné à éviter la création d'objets inutiles.

L'objet délégué met en cache la valeur renvoyée lors du premier accès. Cette valeur mise en cache est utilisée plus loin dans le programme si nécessaire.

Vous pouvez tirer parti de ses getter et setter personnalisés pour les actions intermédiaires lors de la lecture et de l'écriture de valeurs. Je préfère également l'utiliser avec des types immuables, car je pense que cela fonctionne mieux avec des valeurs qui restent inchangées tout au long du programme.

Conclusion

Dans cet article, nous avons discuté du lateinitmodificateur et de la délégation paresseuse de Kotlin. Nous avons montré quelques exemples de base démontrant leurs utilisations et avons également parlé de certains cas d'utilisation pratiques dans le développement d'Android.

Merci d'avoir pris le temps de lire cette entrée jusqu'à la fin ! J'espère que vous pourrez utiliser ce guide pour implémenter ces deux fonctionnalités dans votre parcours de développement d'applications.

Source : https://blog.logrocket.com/initializing-lazy-lateinit-variables-kotlin/

#kotlin 

What is GEEK

Buddha Community

initialisation Des Variables Lazy Et Lateinit Dans Kotlin
Thierry  Perret

Thierry Perret

1660726141

initialisation Des Variables Lazy Et Lateinit Dans Kotlin

Kotlin nous oblige généralement à initialiser les propriétés dès que nous les définissons. Cela semble étrange lorsque nous ne connaissons pas la valeur initiale idéale, en particulier dans le cas des propriétés Android axées sur le cycle de vie.

Heureusement, il existe un moyen de résoudre ce problème. L'éditeur IntelliJ IDEA vous avertira si vous déclarez une propriété de classe sans l'initialiser et vous recommandera d'ajouter un mot- lateinitclé.

Que se passe-t-il si une propriété ou un objet initialisé n'est pas réellement utilisé dans le programme ? Eh bien, ces initialisations inutilisées seront un passif pour le programme puisque la création d'objets est un processus lourd. Ceci est un autre exemple d'où lateinitpeut venir à notre secours.

Cet article explique comment le lateinitmodificateur et la délégation paresseuse peuvent prendre en charge les initialisations précoces inutilisées ou inutiles. Cela rendra votre flux de travail de développement Kotlin plus efficace.

lateinità Kotlin

Le lateinitmot-clé signifie « initialisation tardive ». Lorsqu'il est utilisé avec une propriété de classe, le lateinitmodificateur empêche la propriété d'être initialisée au moment de la construction de l'objet de sa classe.

La mémoire est allouée aux lateinitvariables uniquement lorsqu'elles sont initialisées plus tard dans le programme, plutôt qu'au moment de leur déclaration. C'est très pratique en terme de souplesse d'initialisation.

Regardons quelques fonctionnalités importantes qui lateinita à offrir!

Principales caractéristiques

Premièrement, la mémoire n'est pas allouée à une lateinitpropriété au moment de la déclaration. L'initialisation a lieu plus tard quand bon vous semble.

Une lateinitpropriété peut changer plus d'une fois tout au long du programme et est censée être modifiable. C'est pourquoi vous devez toujours le déclarer comme a varet non comme a valou const.

L' lateinitinitialisation peut vous éviter des vérifications null répétitives dont vous pourriez avoir besoin lors de l'initialisation de propriétés en tant que types nullables. Cette fonctionnalité des lateinitpropriétés ne prend pas en charge le type nullable.

En développant mon dernier point, lateinitpeut être bien utilisé avec des types de données non primitifs. Cela ne fonctionne pas avec les types primitifs comme longou int. En effet, chaque fois qu'une lateinitpropriété est accessible, Kotlin lui fournit une valeur nulle sous le capot pour indiquer que la propriété n'a pas encore été initialisée.

Les types primitifs ne peuvent pas être null, il n'y a donc aucun moyen d'indiquer une propriété non initialisée. En conséquence, les types primitifs lèvent une exception lorsqu'ils sont utilisés avec le lateinitmot clé.

Enfin, une lateinitpropriété doit être initialisée à un moment donné avant d'y accéder, sinon elle générera une UninitializedPropertyAccessExceptionerreur, comme indiqué ci-dessous :

Erreur d'exception d'accès à la propriété non initialisée

Une lateinitpropriété accédée avant l'initialisation conduit à cette exception.

Kotlin permet de vérifier si une lateinitpropriété est initialisée. Cela peut être pratique pour gérer l'exception de désinitialisation dont nous venons de parler.

lateinit var myLateInitVar: String
...

if(::myLateInitVar.isInitialized) {
  // Do something
}

Exemples de lateinitmodificateurs utilisés

Voyons le lateinitmodificateur en action avec un exemple simple. Le code ci-dessous définit une classe et initialise certaines de ses propriétés avec des valeurs factices et nulles.

class TwoRandomFruits {
  var fruit1: String = "tomato" 
  var fruit2: String? = null


  fun randomizeMyFruits() {
      fruit1 = randomFruits()
      fruit2 = possiblyNullRandomFruits()
  }


  fun randomFruits(): String { ... }
  fun possiblyNullRandomFruits(): String? { ... }
}

fun main() {
    val rf= RandomFruits()
    rf.randomizeMyFruits()


    println(rf.fruit1.capitalize())
    println(rf.fruit2?.capitalize()) // Null-check
}

Ce n'est pas la meilleure façon d'initialiser une variable, mais dans ce cas, cela fait toujours le travail.

Comme vous pouvez le voir ci-dessus, si vous choisissez de rendre la propriété nullable, vous devrez la vérifier à chaque fois que vous la modifiez ou l'utilisez. Cela peut être assez fastidieux et ennuyeux.

Abordons ce problème avec le lateinitmodificateur :

class TwoRandomFruits {
  lateinit var fruit1: String // No initial dummy value needed
  lateinit var fruit2: String // Nullable type isn't supported here


  fun randomizeMyFruits() {
      fruit1 = randomFruits()
      fruit2 = when {
          possiblyNullRandomFruits() == null -> "Tomato" // Handling null values
          else -> possiblyNullRandomFruits()!!
      }
  }


  fun randomFruits(): String { ... }
  fun possiblyNullRandomFruits(): String? { ... }
}

fun main() {
    val rf= RandomFruits()
    rf.randomizeMyFruits()


    println(rf.fruit1.capitalize())
    println(rf.fruit2.capitalize())
}

Vous pouvez voir ce code en action ici .

La lateinitmise en œuvre parle d'elle-même et démontre une manière astucieuse de gérer les variables ! Outre le comportement par défaut de lateinit, le principal point à retenir ici est la facilité avec laquelle nous pouvons éviter d'utiliser le type nullable.

Propriétés axées sur le cycle de vie etlateinit

La liaison de données est un autre exemple d'utilisationlateinit pour initialiser une activité ultérieurement. Les développeurs souhaitent souvent initialiser la variable de liaison plus tôt pour l'utiliser comme référence dans d'autres méthodes pour accéder à différentes vues.

Dans la MainActivityclasse ci-dessous, nous avons déclaré la liaison avec le lateinitmodificateur pour obtenir la même chose.

package com.test.lateinit

import androidx.appcompat.app.AppCompatActivity
import ...

class MainActivity : AppCompatActivity() {
  lateinit var binding: ActivityMainBinding

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = DataBindingUtil.setContentView(this, R.layout.activity_main)

    ...
  }
  ...
}

La liaison pour MainActivityne peut être initialisée qu'une fois que la fonction de cycle de vie de l'activité, onCreate(), est déclenchée. Par conséquent, déclarer la liaison avec le lateinitmodificateur prend tout son sens ici.

Quand utiliserlateinit

Avec l'initialisation de variable régulière, vous devez ajouter une valeur fictive et, très probablement, une valeur nulle. Cela ajoutera beaucoup de vérifications nulles chaque fois qu'elles seront consultées.

// Traditional initialization
var name: String? = null
...    
name = getDataFromSomeAPI()
...
// A null-check will be required whenever `name` is accessed.
name?.let { it-> 
  println(it.uppercase())
}

// Lateinit initialization
lateinit var name: String
...
name = getDatafromSomeAPI()
...
println(name.uppercase())

Nous pouvons utiliser le lateinitmodificateur pour éviter ces vérifications nulles répétées, en particulier lorsqu'une propriété est susceptible de fluctuer fréquemment.

Choses à retenir lors de l'utilisationlateinit

Il est bon de se rappeler de toujours initialiser une lateinitpropriété avant d'y accéder, sinon, vous verrez une grosse exception levée au moment de la compilation.

Assurez-vous également de conserver la propriété modifiable en utilisant une vardéclaration. Utiliser valet constn'aura aucun sens, car ils indiquent des propriétés immuables avec lesquelles lateinitne fonctionneront pas.

Enfin, évitez d'utiliser lateinitlorsque le type de données de la propriété donnée est primitif ou que les chances d'une valeur nulle sont élevées. Il n'est pas conçu pour ces cas et ne prend pas en charge les types primitifs ou nullables.

Délégation paresseuse à Kotlin

Comme son nom l'indique, lazyKotlin initialise une propriété de manière paresseuse. Essentiellement, il crée une référence mais ne va pour l'initialisation que lorsque la propriété est utilisée ou appelée pour la première fois.

Maintenant, vous vous demandez peut-être en quoi cela diffère de l'initialisation régulière. Eh bien, au moment de la construction d'un objet de classe, toutes ses propriétés publiques et privées sont initialisées dans son constructeur. Il y a une surcharge associée à l'initialisation des variables dans une classe ; plus il y a de variables, plus la surcharge sera importante.

Comprenons-le avec un exemple:

class X {
  fun doThis() {}
}

class Y {
  val shouldIdoThis: Boolean = SomeAPI.guide()
  val x = X()

  if(shouldIdoThis) {
    x.doThis()
  }
  ...
}

Bien qu'il ne l'utilise pas, class Ydans le code ci-dessus a toujours un objet créé de class X. La classe Xralentira également Ys'il s'agit d'une classe fortement construite.

La création d'objets inutiles est inefficace et peut ralentir la classe en cours. Il se peut que certaines propriétés ou certains objets ne soient pas requis dans certaines conditions, selon le déroulement du programme.

Il se peut également que des propriétés ou des objets reposent sur d'autres propriétés ou objets pour la création. La délégation paresseuse traite efficacement ces deux possibilités.

Principales caractéristiques

Une variable avec une initialisation différée ne sera pas initialisée tant qu'elle n'aura pas été appelée ou utilisée. De cette façon, la variable n'est initialisée qu'une seule fois, puis sa valeur est mise en cache pour une utilisation ultérieure dans le programme.

Puisqu'une propriété initialisée avec la délégation différée est censée utiliser la même valeur partout, elle est de nature immuable et est généralement utilisée pour les propriétés en lecture seule. Vous devez le marquer d'une valdéclaration.

Il est thread-safe, c'est-à-dire calculé une seule fois et partagé par tous les threads par défaut. Une fois initialisé, il se souvient ou met en cache la valeur initialisée tout au long du programme.

Contrairement à lateinit, la délégation différée prend en charge un setter et un getter personnalisés qui lui permettent d'effectuer des opérations intermédiaires lors de la lecture et de l'écriture de la valeur.

Exemple de délégation paresseuse en cours d'utilisation

Le code ci-dessous implémente des calculs simples pour calculer les aires de certaines formes. Dans le cas d'un cercle, le calcul nécessiterait une valeur constante pour pi.

class Area {
  val pi: Float = 3.14f


  fun circle(radius: Int): Float = pi * radius * radius
  fun rectangle(length: Int, breadth: Int = length): Int = length * breadth
  fun triangle(base: Int, height: Int): Float = base * height * .5f
}

fun main() {
  val area = Area()
  val squareSideLength = 51


  println("Area of our rectangle is ${area.rectangle(squareSideLength)}")
}

Comme vous pouvez le voir ci-dessus, aucun calcul de l'aire d'un cercle n'a été effectué, ce qui rend notre définition de piinutile. La propriété piest toujours initialisée et allouée de la mémoire.

Corrigeons ce problème avec la délégation paresseuse :

class Area {
  val pi: Float by lazy {
    3.14f
  } 


  fun circle(...) = ...
  fun rectangle(...) = ...
  fun triangle(...) = ...
}

fun main() {
  val area = Area()
  val squareSideLength = 51
  val circleRadius = 37

  println("Area of our rectangle is ${area.rectangle(squareSideLength)}")
  println("Area of our circle is ${area.circle(circleRadius)}")
}

Vous pouvez voir une démo de l'exemple ci-dessus ici .

L'implémentation ci-dessus de la délégation paresseuse n'est utilisée pique lorsqu'elle est accessible. Une fois accessible, sa valeur est mise en cache et réservée pour être utilisée tout au long du programme. Nous le verrons en action avec des objets dans les exemples suivants.

Actions intermédiaires

Voici comment vous pouvez ajouter des actions intermédiaires lors de l'écriture de valeurs via la délégation paresseuse. Le code ci-dessous lazyinitialise a TextViewdans une activité Android.

Chaque fois que cela TextViewest appelé pour la première fois dans le MainActivity, un message de débogage avec une LazyInitbalise sera enregistré, comme indiqué ci-dessous dans la fonction lambda du délégué :

...
class MainActivity : AppCompatActivity() {
  override fun onCreate(...) {
    ...  
    val sampleTextView: TextView by lazy {
      Log.d("LazyInit", "sampleTextView")
      findViewById(R.id.sampleTextView)
    }
  }
  ...
}

Délégation paresseuse dans les applications Android

Passons maintenant à l'application de la délégation paresseuse dans les applications Android. Le cas d'utilisation le plus simple peut être notre exemple précédent d'une activité Android qui utilise et manipule une vue de manière conditionnelle.

package com.test.lazy

import androidx.appcompat.app.AppCompatActivity
import ...

class MainActivity : AppCompatActivity() {
  lateinit var binding: ActivityMainBinding

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = DataBindingUtil.setContentView(this, R.layout.activity_main)


    val sharedPrefs by lazy {
      activity?
        .getPreferences(Context.MODE_PRIVATE)
    } 


    val startButton by lazy {
      binding.startButton
    }


    if(sharedPrefs.getBoolean("firstUse", true)) {
      startButton.isVisible = true
      startButton.setOnClickListener {
        // Finish onboarding, move to main screen; something like that
        sharedPrefs.setBoolean("firstUse", false)
      }
    }

  }
}

Ci-dessus, nous avons initialisé the SharedPreferenceset a Buttonavec une délégation paresseuse. La logique implique la mise en œuvre d'un écran d'intégration basé sur une valeur booléenne extraite des préférences partagées.

La différence entre by lazyet= lazy

L' by lazyinstruction ajoute une amélioration par le délégué paresseux directement à une propriété donnée. Son initialisation ne se fera qu'une seule fois lors de son premier accès.

val prop by lazy {
  ...
}

D'autre part, l' = lazyinstruction contient à la place une référence à l'objet délégué, par lequel vous pouvez utiliser la isInitialized()méthode de délégation ou y accéder avec la valuepropriété.

val prop = lazy {
  ...
}
...

if(prop.isInitialized()) {
  println(prop.value)
}

Vous pouvez voir une démo rapide du code ci-dessus ici.

Quand utiliserlazy

Envisagez d'utiliser des délégués paresseux pour alléger une classe qui implique des créations multiples et/ou conditionnelles d'autres objets de classe. Si la création d'objet dépend d'une propriété interne de la classe, la délégation paresseuse est la solution.

class Employee {
    ...
    fun showDetails(id: Int): List<Any> {
        val employeeRecords by lazy {
            EmployeeRecords(id) // Object's dependency on an internal property
        }
    }
    ...
}

Choses à retenir lors de l'utilisationlazy

L'initialisation différée est une délégation qui initialise quelque chose une seule fois et uniquement lorsqu'il est appelé. Il est destiné à éviter la création d'objets inutiles.

L'objet délégué met en cache la valeur renvoyée lors du premier accès. Cette valeur mise en cache est utilisée plus loin dans le programme si nécessaire.

Vous pouvez tirer parti de ses getter et setter personnalisés pour les actions intermédiaires lors de la lecture et de l'écriture de valeurs. Je préfère également l'utiliser avec des types immuables, car je pense que cela fonctionne mieux avec des valeurs qui restent inchangées tout au long du programme.

Conclusion

Dans cet article, nous avons discuté du lateinitmodificateur et de la délégation paresseuse de Kotlin. Nous avons montré quelques exemples de base démontrant leurs utilisations et avons également parlé de certains cas d'utilisation pratiques dans le développement d'Android.

Merci d'avoir pris le temps de lire cette entrée jusqu'à la fin ! J'espère que vous pourrez utiliser ce guide pour implémenter ces deux fonctionnalités dans votre parcours de développement d'applications.

Source : https://blog.logrocket.com/initializing-lazy-lateinit-variables-kotlin/

#kotlin 

Juned Ghanchi

1621508255

Kotlin App Development Company in India, Hire Kotlin Developers

We are a prime Kotlin app developer in India. We build and provide the best personalized Android apps, migration services, ongoing maintenance, and management.

We have the most efficient Kotlin developers that build ultramodern, interactive, and secure mobile apps. The technologies we use to create the most advanced Kotlin apps are AR/VR, AI/ML, IoT, etc.

Hire Kotlin app developers in India. Meet us, and we will help you meet all of your technology requirements.

#kotlin app development company india #hire kotlin developers india #kotlin app development company #hire kotlin developers #kotlin development agency #kotlin app programmers

Hire Dedicated Kotlin Developer - WebClues Infotech

The most popular language used for Android app development is Kotlin and recently Kotlin also launched its Cross-Platform app development language Kotlin Multiplatform.

So are you looking to launch a mobile using Kotlin as your Programming Language?

Then you are at the right place as WebClues Infotech offers services to Hire a Dedicated Kotlin Developer who can develop an interactive and rich user-experienced mobile app. Also, WebClues has a flexible pricing model that the business can choose according to its most suitable structure.

So what are you waiting for? Hire a dedicated Kotlin developer from a reputed Web & Mobile app development agency that has successfully served more than 600+ clients.

Get in touch with us!!

Book Free Interview: https://bit.ly/3dDShFg

#hire dedicated kotlin developer #hire dedicated kotlin developer #hire kotlin developers #hire kotlin developer #hire dedicated kotlin app developer #hire kotlin app developers india

How to Develop an Android App with Kotlin?

Do you have an idea to develop an android app using Kotlin?

Are you looking for the best Kotlin app development company in the USA? We at AppClues Infotech offering versatile mobile app development services in the USA. We provide custom mobile app development solutions as per your specific business needs with the prevailing market trending technology & features.

Hire our top-notch Kotlin app designers & developers for your project at a cost-effective price.

Our Kotlin App Development Services:
• Custom Android App Development
• Kotlin AR/VR App Development
• Kotlin App UI/UX Design
• Kotlin App QA & Testing- code Optimization
• Kotlin App Migrations
• Kotlin App Maintenance and Upgrades

For more info:
Website: https://www.appcluesinfotech.com/
Email: info@appcluesinfotech.com
Call: +1-978-309-9910

#kotlin android app development company #best kotlin android app development usa #kotlin android app development #kotlin for android app development #kotlin mobile app development service #create android app with kotlin

Top Kotlin Android App Development Company in USA

Looking for a top Kotlin Android app development company for creating an Android app project? AppClues Infotech is a top Kotlin Android app development company in USA that delivers the most scalable and efficient Kotlin app development services globally.

For more info:
Website: https://www.appcluesinfotech.com/
Email: info@appcluesinfotech.com
Call: +1-978-309-9910

#kotlin android app development company #best kotlin android app development usa #kotlin android app development #kotlin for android app development #kotlin mobile app development service #create android app with kotlin