versioning schema dei dati nella memoria interna di Android

3

Utilizzo la memoria interna di Android per conservare i dati per la mia applicazione e sto cercando di trovare un buon modo per gestire i dati di lettura di uno schema precedente. Ad esempio, supponiamo di aver serializzato e scritto diverse istanze di dati di classe in un file

public class Data{
    private String text;
    public Data(text){
        this.text = text;
    }
}

e in seguito ho letto che i dati sono stati riclassificati e trasmessi su (Dati). Ma poi dì che cambio Data per apparire come questo

public class Data{
    private String name;
    public Data(name){
        this.name = name;
    }
}

ora che la proprietà è denominata in modo diverso, quando leggo i dati che sono stati salvati nello schema originale, non sarà possibile trasmettere facilmente al nuovo tipo. Quali sono alcune soluzioni per la versione dei dati in modo che io possa leggere i vecchi dati e trasmetterli a un nuovo tipo?

    
posta one stevy boi 06.05.2014 - 19:58
fonte

1 risposta

2

È difficile rispondere con le informazioni fornite. Ad esempio, dici di "stringificare" i dati, ma non stai dicendo quale metodo stai usando. C'è una libreria che stai usando? La stringa JSON, XML o altri dati strutturati?

Suppongo che tu stia utilizzando qualche tipo di dati strutturati (per semplicità, diciamo JSON che usa GSON o simili).

Quindi al momento della scrittura, creerai e scrivi una stringa

public void writeToFile(String filname, Object myObject) {

    String serialized = new Gson().toJson(myObject);

    try(FileOutputStreamoutputStream output =
            openFileOutput(filename, Context.MODE_PRIVATE)
    ) {
        output.write(s.getBytes());
    } catch (Exception e) {
        Log.e("MyApplication",
              "Unable to write " + serialized + " to file " + filename + " with exception",
              e
        );
    }
}

E al momento della lettura, ti basterà leggere i dati indietro. Bene, è piuttosto facile

public <T> T read(String filename, Class<T> clazz) {

    String serialized = new Gson().toJson(myObject);

    try (
            BufferedReader reader = new BufferedReader(
                new InputStreamReader(
                    openFileInput(filename, Context.MODE_PRIVATE)
                )
            )
    ) {
        StringBuilder json = new StringBuilder();

        String line;
        while((line = reader.nextLine()) != null) {
            json.append(line);
        }
        return new Gson().fromJson(json.toString, clazz);
    } catch (Exception e) {
        Log.e(
            "MyApplication",
            "Unable to read " + filename + " to class " + clazz.simpleName() + " with exception",
            e
        );
        return null;
    }
}

Ma aspetta, hai detto che hai cambiato il nome di un campo. Bene, la soluzione più semplice è semplicemente non aver cambiato il nome di detto campo. Ma questo è il mondo reale, ci sono requisiti aziendali, sviluppatori pomposi che sanno più dei loro predecessori, o qualsiasi altra cosa. Hai ereditato il codice. Non ho intenzione di incolparti per questo.

Quindi, la prossima soluzione più semplice è quella di mantenere le versioni precedenti delle tue classi. Ad esempio, puoi avvolgere la tua funzione di lettura con

public <T> T readFromFile(String filename, Transformer<T> optimusPrime) {

    for(Class clazz : optimusPrime.getSupportedClasses()) {
        //TODO optimize this (haha, like that'll get prioritized)
        Object o = read(filename, supportedIterator.next())
        if(o != null) {
            return optimusPrime.transform(o)
        }
    }

    return null;
}

Dove la classe del trasformatore ha una raccolta di tutte le possibili classi che potrebbero essere mai state memorizzate nel file (si spera in ordine dal più o meno probabile), e un metodo generale per tradurre tra loro. Probabilmente sarebbe simile a questo

public class OptimusPrime implements Transformer<Autobot> {

    private final Map<Class, TransformMethod> transformations;

    public OptimusPrime() {
        transformations = new TreeMap<>;
        transformations.put(Megatron.class, new MegatronTransform());
        transformations.put(Starscream.class, new StarscreamTransform());
        transformations.put(Shockwave.class, new ShockwaveTransform());
        //Shhhh 
    }

    @Override
    public Collection<Class> getSupportedClasses() {
        return transformations.keySet();
    }

    @Override
    public Autobot transform(Object o) {
        TransformMethod<Autobot> transformation = transformations.get(o.getClass());
        return (transformation == null) ? null : transformation.transform(o);
    }

}

E

public class MegatronTransform implements TransformMethod<Autobot> {
    @Override
    public Megatron transform(Object o){
        return (Megatron) o;
    }
}

Quindi, è fattibile, ma il tuo codice base si gonfierà e non sarai mai in grado di sbarazzarti di tutte quelle vecchie classi nel tuo codice a meno che tu non fornisca all'utente qualche errore e metodo di recupero, o tu? re sicuro al 100% che nessun utente abbia il tipo di dati legacy memorizzato sul proprio dispositivo.

Quale sarebbe l'opzione più semplice (più costosa) sarebbe quella di archiviare i dati all'interno di un'API con versione da qualche parte nel "cloud". In questo modo puoi avere il controllo sui dati e sul meccanismo di archiviazione.

    
risposta data 04.06.2016 - 03:50
fonte

Leggi altre domande sui tag