web-dev-qa-db-fra.com

Composants d'architecture Android: Utilisation d'énums

Est-il possible d'utiliser un type Enum en tant que champ intégré dans une classe d'entité avec les nouveaux composants d'architecture Android et la bibliothèque de persistance de la salle

Mon entité (avec énumération intégrée):

@Entity(tableName = "tasks")
public class Task extends SyncEntity {

    @PrimaryKey(autoGenerate = true)
    String taskId;

    String title;

    /** Status of the given task.
     * Enumerated Values: 0 (Active), 1 (Inactive), 2 (Completed)
     */
    @Embedded
    Status status;

    @TypeConverters(DateConverter.class)
    Date startDate;

    @TypeConverters(StatusConverter.class)
    public enum Status {
        ACTIVE(0),
        INACTIVE(1),
        COMPLETED(2);

        private int code;

        Status(int code) {
            this.code = code;
        }

        public int getCode() {
            return code;
        }
    }
}

Mon Convertisseur Type:

public class StatusConverter {

    @TypeConverter
    public static Task.Status toStatus(int status) {
        if (status == ACTIVE.getCode()) {
            return ACTIVE;
        } else if (status == INACTIVE.getCode()) {
            return INACTIVE;
        } else if (status == COMPLETED.getCode()) {
            return COMPLETED;
        } else {
            throw new IllegalArgumentException("Could not recognize status");
        }
    }

    @TypeConverter
    public static Integer toInteger(Task.Status status) {
        return status.getCode();
    }
}

Lorsque je compile cette information, une erreur s'affiche: Erreur: (52, 12) erreur: les entités et les pojos doivent avoir un constructeur public utilisable. Vous pouvez avoir un constructeur vide ou un constructeur dont les paramètres correspondent aux champs (par nom et type). '

Mise à jour 1 Ma classe SyncEntity:

/** * Classe de base pour toutes les entités de salle synchronisées . * /

@Entity
public class SyncEntity {

    @ColumnInfo(name = "created_at")
    Long createdAt;

    @ColumnInfo(name = "updated_at")
    Long updatedAt;
}
18
Bohsen

Je peux utiliser les valeurs enum à Room avec TypeConverters. Il y a quelques parties à changer à votre code: 

1) Vous devez déclarer les champs de votre entité publics ou avoir des getters/setters publics. Ou vous obtiendrez l'erreur ci-dessous:

yourField n'est pas public dans YourEntity; ne peut être consulté à partir de forfait extérieur

2) Vous n'avez pas besoin de l'annotation @Embedded pour votre champ status. C'est pour les objets imbriqués. Plus de docs.

3) Vous n'avez pas utilisé l'annotation @TypeConverters au bon endroit. Dans votre cas, il peut être défini au-dessus du champ status. Plus de docs.

4) Vous devez définir un constructeur pour votre entité ou vous obtiendrez l'erreur ci-dessous:

Les entités et les pojos doivent avoir un constructeur public utilisable. Vous pouvez avoir un constructeur vide ou un constructeur dont les paramètres correspondent aux champs (par nom et type).

Vous pouvez définir un constructeur vide pour ignorer cette erreur.

5) Utilisez int au lieu d'Integer dans votre TypeConverter.

Somme; ci-dessous fonctionne comme prévu:

@Entity(tableName = "tasks")
public class Task extends SyncEntity {

    @PrimaryKey(autoGenerate = true)
    public String taskId;

    public String title;

    /** Status of the given task.
     * Enumerated Values: 0 (Active), 1 (Inactive), 2 (Completed)
     */
    @TypeConverters(StatusConverter.class)
    public Status status;

    @TypeConverters(DateConverter.class)
    public Date startDate;

    // empty constructor 
    public Task() {
    }

    public enum Status {
        ACTIVE(0),
        INACTIVE(1),
        COMPLETED(2);

        private int code;

        Status(int code) {
            this.code = code;
        }

        public int getCode() {
            return code;
        }
    }
}
30
Devrim

J'ai rencontré un problème similaire. La réponse de Devrim à ce sujet a été très utile. Cependant, mon entité a un nullable. 

Dans ce cas, l'opération d'insertion renvoie une erreur. Cela est dû au membre primitif "code" du type enum.

J'ai développé l'implémentation suivante pour résoudre cette erreur.

D'abord j'ai fixé le type enum comme suit.

package com.example.models.entities.enums;


import androidx.room.TypeConverter;

public enum Status {
    ACTIVE(0),
    INACTIVE(1),
    COMPLETED(2);

    private final Integer code;

    Status(Integer value) {
        this.code = value;
    }
    public Integer getCode() {
        return code;
    }

    @TypeConverter
    public static Status getStatus(Integer numeral){
        for(Status ds : values()){
            if(ds.code == numeral){
                return ds;
            }
        }
        return null;
    }

    @TypeConverter
    public static Integer getStatusInt(Status status){

        if(status != null)
            return status.code;

        return  null;
    }

}

Ensuite, j'ai mis à jour l'entité comme suit.

package com.example.models.entities;


import com.example.models.TypeConverters.DateConverter;
import com.example.models.entities.enums.Status;

import Java.util.Date;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
import androidx.room.TypeConverters;

@Entity(tableName = "tasks")
@TypeConverters({Status.class, DateConverter.class})

public class Task extends SyncEntity {

    @PrimaryKey(autoGenerate = true)
    String taskId;

    @NonNull
    String title;

    /** Status of the given task.
     * Enumerated Values: 0 (Active), 1 (Inactive), 2 (Completed)
     */
    @Nullable
    Status status;

    @NonNull
    Date startDate;


    public String getTaskId() {
        return taskId;
    }

    public void setTaskId(String taskId) {
        this.taskId = taskId;
    }

    @NonNull
    public String getTitle() {
        return title;
    }

    public void setTitle(@NonNull String title) {
        this.title = title;
    }

    @Nullable
    public Status getStatus() {
        return status;
    }

    public void setStatus(@Nullable Status status) {
        this.status = status;
    }

    @NonNull
    public Date getStartDate() {
        return startDate;
    }

    public void setStartDate(@NonNull Date startDate) {
        this.startDate = startDate;
    }
}

Ainsi, je pouvais gérer la propriété nullable enum dans la base de données Room.

J'espère que j'ai pu aider avec une situation similaire.

Bonne codage.

2
Hasan BINBOGA