web-dev-qa-db-de.com

Android-Architekturkomponenten: Verwenden von Enums

Ist es möglich, einen Aufzählungstyp als eingebettetes Feld in einer Entity-Klasse mit der neuen Android-Architekturkomponenten- und Raumpersistenzbibliothek zu verwenden?

Meine Entität (mit eingebettetem Enum):

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

Mein TypeConverter:

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();
    }
}

Wenn ich das kompiliere, erhalte ich die Fehlermeldung 'Error: (52, 12) error: Entities und Pojos müssen einen verwendbaren öffentlichen Konstruktor haben. Sie können einen leeren Konstruktor oder einen Konstruktor haben, dessen Parameter mit den Feldern übereinstimmen (nach Name und Typ). '

Update 1 Meine SyncEntity-Klasse:

/** * Basisklasse für alle Raumobjekte, die synchronisiert werden . * /

@Entity
public class SyncEntity {

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

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

Ich kann enum-Werte bei Room mit TypeConverters verwenden. Es gibt einige Teile, die Sie an Ihrem Code ändern können: 

1) Sie müssen die Felder Ihrer Entität für öffentlich erklären oder sie müssen über öffentliche Getter/Setter verfügen. Oder du bekommst einen Fehler:

yourField ist in YourEntity nicht öffentlich; kann nicht von .__ aus aufgerufen werden. außerhalb paket

2) Sie benötigen die @Embedded-Annotation nicht für Ihr status-Feld. Es ist für verschachtelte Objekte. Mehr aus docs.

3) Sie haben die @TypeConverters-Annotation nicht an der richtigen Stelle verwendet. In Ihrem Fall kann es über dem Feld status gesetzt werden. Mehr aus docs.

4) Sie müssen einen Konstruktor für Ihre Entität definieren, da andernfalls folgende Fehlermeldung angezeigt wird:

Entitäten und Pojos müssen über einen verwendbaren öffentlichen Konstruktor verfügen. Sie können einen leeren Konstruktor oder einen Konstruktor haben, dessen Parameter mit den Feldern übereinstimmen (nach Name und Typ).

Sie können einen leeren Konstruktor definieren, um diesen Fehler zu überspringen.

5) Verwenden Sie in Ihrem TypeConverter int anstelle von Integer.

Summe; unten funktioniert wie erwartet:

@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

Ich bin auf ein ähnliches Problem gestoßen. Devrims Antwort auf das Thema war sehr hilfreich. Meine Entität hat jedoch einen nullwert. 

In diesem Fall gibt die Einfügeoperation einen Fehler zurück. Dies wird durch das primitive Element "code" im Aufzählungstyp verursacht.

Ich habe die folgende Implementierung entwickelt, um diesen Fehler zu beheben.

Zuerst habe ich den Aufzählungstyp wie folgt festgelegt.

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

}

Dann habe ich die Entität wie folgt aktualisiert.

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

So konnte ich in der Raumdatenbank nullfähige Enumeneigenschaften verwalten.

Ich hoffe, ich konnte in einer ähnlichen Situation helfen.

Glückliche Kodierung.

2
Hasan BINBOGA