2 votes

La requête de la base de données de la chambre renvoie null là où elle devrait être null-safe en Kotlin

J'ai une requête qui n'a pas de résultat, lorsque la DB est vide. Par conséquent NULL est la valeur de retour correcte.

Cependant, le compilateur dans Android Studio me donne l'avertissement :
La condition 'maxDateTime != null' est toujours 'true'.

Si je débogue le code, la vérification de null fonctionne correctement car la valeur est en réalité null.

Quand je réécris l'interface en 'fun queryMaxServerDate(): String?' (remarquez le point d'interrogation), l'avertissement du compilateur disparait.

Mais ne devrait pas 'fun queryMaxServerDate(): String' résulter en une erreur de compilation puisque cela peut être null ?

@Dao
interface CourseDao {

    // Obtenir la dernière entrée téléchargée
    @Query("SELECT MAX(${Constants.COL_SERVER_LAST_MODIFIED}) from course")
    fun queryMaxServerDate(): String

}

// appel de fonction
/**
 * @return Date serveur la plus élevée dans la table en millisecondes ou 1 en cas de vide/erreur.
 */
fun queryMaxServerDateMS(): Long {
    val maxDateTime = courseDao.queryMaxServerDate()

    var timeMS: Long = 0
    if (maxDateTime != null) { // Avertissement : La condition 'maxDateTime != null' est toujours 'true'
        timeMS = TimeTools.parseDateToMillisOrZero_UTC(maxDateTime)
    }
    return if (timeMS <= 0) 1 else timeMS
}

2voto

MikeT Points 12446

Le code sous-jacent généré par l'annotation est java et donc l'exception à la sécurité nulle comme suit :-

Le système de type de Kotlin vise à éliminer les NullPointerException de notre code. Les seules causes possibles de NPE peuvent être :

Un appel explicite à throw NullPointerException(); Utilisation de l'opérateur !! tel que décrit ci-dessous;

Une incohérence des données concernant l'initialisation, par exemple lorsque:

  • Un this non initialisé disponible dans un constructeur est passé et utilisé quelque part ("fuite de this");
  • Un constructeur de superclasse appelle un membre ouvert dont l'implémentation dans la classe dérivée utilise un état non initialisé;
  • Interopérabilité Java:
    • Tentatives d'accès à un membre sur une référence nulle d'un type de plate-forme;
    • Types génériques utilisés pour l'interopérabilité Java avec une nullabilité incorrecte, par exemple un morceau de code Java pourrait ajouter null dans un MutableList Kotlin, signifiant que MutableList devrait être utilisée pour travailler avec celui-ci;
    • D'autres problèmes causés par du code Java externe.

Sécurité Nulle

par exemple, le code généré pour queryMaxServerDate() dans CourseDao serait le suivant :-

  @Override
  public String queryMaxServerDate() {
    final String _sql = "SELECT max(last_mopdified) from course";
    final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 0);
    __db.assertNotSuspendingTransaction();
    final Cursor _cursor = DBUtil.query(__db, _statement, false, null);
    try {
      final String _result;
      if(_cursor.moveToFirst()) {
        final String _tmp;
        _tmp = _cursor.getString(0);
        _result = _tmp;
      } else {
        _result = null;
      }
      return _result;
    } finally {
      _cursor.close();
      _statement.release();
    }
  }

Comme vous pouvez le constater, aucune donnée extraite (pas de première ligne) et null est retourné.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X