Evitar recrear Gson instancias para el Tipo de Habitación Convertidores

Alternativamente, la pregunta podría ser titulado: Evitar el uso de un Singleton Util como un Gson de contenedor.

En mi proyecto Android que utiliza la Sala de persistencia, tengo unas cuantas entidades donde ciertas columnas no son tipos primitivos. Después de mirar alrededor para un poco, he encontrado que el uso de TypeConverter a lo largo de con Gson para convertir a los no-de los tipos primitivos y de las cadenas es una solución digna.

Ahora, la clase que alberga el 0e las ss se parece a esto:

class Converters {
    ...

    @TypeConverter
    public static Long fromDate(Date date) {
        return date == null ? null : date.getTime();
    }

    @TypeConverter
    public static Date toDate(Long timestamp) {
        return timestamp == null ? null : new Date(timestamp);
    }

    @TypeConverter
    public static String fromAddressData(AddressData addressData) {
        Gson gson = new GsonBuilder()
                .registerTypeAdapter(AddressData.class, new AddressDataAdapter())
                .create();
        return gson.toJson(addressData);
    }

    @TypeConverter
    public static AddressData toAddressData(String addressDataString) {
        Gson gson = new GsonBuilder()
                .registerTypeAdapter(AddressData.class, new AddressDataAdapter())
                .create();
        return gson.fromJson(addressDataString, AddressData.class);
    }

    @TypeConverter
    public static String fromUserData(UserData userData) {
        Gson gson = new Gson();
        return gson.toJson(userData);
    }

    @TypeConverter
    public static UserData toUserData(String userDataString) {
        Gson gson = new Gson();
        return gson.fromJson(userDataString, UserData.class);
    }

    @TypeConverter
    public static String fromCollectionData(CollectionData data) {
        Gson gson = new GsonBuilder()
                .registerTypeAdapter(CollectionData.class, new CollectionDataAdapter())
                .create();
        return gson.toJson(data, CollectionData.class);
    }

    @TypeConverter
    public static CollectionData toCollectionData(String dataString) {
        Gson gson = new GsonBuilder()
                .registerTypeAdapter(CollectionData.class, new CollectionDataAdapter())
                .create();
        return gson.fromJson(dataString, CollectionData.class);
    }

    @TypeConverter
    public static String fromRequestNoteList(List<RequestNote> noteList) {
        Gson gson = new Gson();
        return gson.toJson(noteList, RequestNote.LIST_TYPE);
    }

    @TypeConverter
    public static List<RequestNote> toRequestNoteList(String noteListString) {
        Gson gson = new Gson();
        return gson.fromJson(noteListString, RequestNote.LIST_TYPE);
    }

    @TypeConverter
    public static String fromRequestState(RequestState requestState) {
        Gson gson = new Gson();
        return gson.toJson(requestState);
    }

    @TypeConverter
    public static RequestState toRequestState(String requestStateString) {
        Gson gson = new Gson();
        return gson.fromJson(requestStateString, RequestState.class);
    }

    ...
}

Mi pregunta es; ¿es correcto y aceptable tener una configuración como esta? Si tengo el número de filas que se obtienen utilizando una Sala de DAO, cada fila de llamada asociado un TypeConverter? No tiene que añadir un poco de sobrecarga debido a la creación de un Gson de instancia cada vez?

Ahora, no me gusta este programa de instalación. Se siente como innecesaria la creación de instancias. Para evitar esto, terminé con un Singleton Gson de contenedor. Puedo acceder a él desde cualquier lugar y es más o menos util.

public class DeSerializer {
    //Added formatters; please ignore the ignorance towards proper localization
    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd, MMM, yyyy", Locale.ENGLISH);
    private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("hh:mm a", Locale.ENGLISH);
    private static final SimpleDateFormat DATETIME_FORMAT = new SimpleDateFormat("dd, MMM, yyyy, hh:mm a", Locale.ENGLISH);

    private static final DecimalFormat DISTANCE_FORMAT = new DecimalFormat("#.00 km");

    //Singleton gson instance
    private static Gson mGson;

    public static Gson gson() {
        if(mGson == null) {
            synchronized (DeSerializer.class) {
                if(mGson == null) {
                    mGson = new GsonBuilder()
                            .registerTypeAdapter(AddressData.class, new AddressDataAdapter())
                            .registerTypeAdapter(ImageData.class, new ImageDataAdapter())
                            .registerTypeAdapter(CollectionData.class, new CollectionDataAdapter())
                            .create();
                }
            }
        }

        return mGson;
    }

    //Gson wrapper methods
    public static String toJson(Object src) {
        return gson().toJson(src);
    }

    public static String toJson(Object src, Type typeOfSrc) {
        return gson().toJson(src, typeOfSrc);
    }

    public static <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException {
        return gson().fromJson(json, classOfT);
    }

    public static <T> T fromJson(String json, Type typeOfT) throws JsonSyntaxException {
        return gson().fromJson(json, typeOfT);
    }

    public static <T> T fromJson(String json, TypeToken<T> typeTokenOfT) throws JsonSyntaxException {
        return fromJson(json, typeTokenOfT.getType());
    }

    //Additional utility; please ignore the blurred boundaries of single responsibility
    public static JsonObject jsonWebTokenPayload(String token) {
        String[] parts = token.split("\\.");
        String json = new String(Base64.decode(parts[1], Base64.URL_SAFE));
        return gson().fromJson(json, JsonObject.class);
    }

    public static <T extends Parcelable> T getParcelable(Bundle data, String key, ClassLoader loader) {
        data.setClassLoader(loader);
        return data.getParcelable(key);
    }

    public static String dateString(Date date) {
        return DATE_FORMAT.format(date);
    }

    public static String timeString(Date date) {
        return TIME_FORMAT.format(date);
    }

    public static String datetimeString(Date date) {
        return DATETIME_FORMAT.format(date);
    }

    public static String distanceString(Number distance) {
        return DISTANCE_FORMAT.format((double) distance / 1000);
    }
}

A continuación, en el Converters de la clase, puedo usar DeSerializer en lugar de tener que crear una instancia de un relevante Gson de instancia cada vez.

Excepto los Únicos supuestamente están mal. Cuando digo supuestamente, quiero decir que, debido a mi falta de entendimiento, soy incapaz de ver por qué esta configuración es malo. Quiero decir, sé que no es la mejor solución, o incluso decente, pero soy incapaz de pensar en otra cosa sin el uso de singleton como una muleta.

DeSerializer no es un buen dependencia, y, en mi ignorancia, quiero decir que la capacidad de prueba no es un problema, ya que no puede ver un caso en el que me gustaría falso o talón DeSerializer.

Así, la segunda parte de mi pregunta es; es esta configuración aceptable? O es romper todas las reglas de la arquitectura limpia?

Lo que se recomienda en este caso, donde no puedo inyectar una dependencia en Converters, pero tampoco quiero seguir teniendo a recrear Gson instancias?

+1
2019-09-17 08:59:10
fuente
0 respuestas

Vea otras preguntas sobre etiquetas