armazenar e recuperar um objeto de classe em preferência compartilhada


111

No Android, podemos armazenar um objeto de uma classe em preferência compartilhada e recuperar o objeto mais tarde?

Se é possível como fazer? Se não for possível, quais são as outras possibilidades de fazê-lo?

Eu sei que a serialização é uma opção, mas estou procurando possibilidades usando a preferência compartilhada.




Aqui está uma resposta a uma pergunta semelhante.
tpk


Você pode usar esta biblioteca que tem muitos recursos embutidos. github.com/moinkhan-in/PreferenceSpider
Moinkhan

Respostas:


15

Não é possivel.

Você só pode armazenar valores simples em SharedPrefences SharePreferences.Editor

E em particular sobre a classe que você precisa salvar?


1
Obrigado. Eu quero armazenar alguns membros de dados da classe. E eu não quero armazenar cada valor de membros de dados usando preferência compartilhada. Eu quero armazená-lo como um objeto. Se não for preferência compartilhada, quais são minhas outras opções?
androidGuy

5
Serializar e armazenar, em um banco de dados (SQLite) / em um arquivo plano.
Blundell

5
A resposta não está completa. A solução possível é transformar o pojo em ByteArrayOutPutStream e salvar como String em
SharedPreferences

27
outra opção é salva como json e mapeada de volta. Com GSON ou jackSON é realmente fácil
rallat em

2
deixe-me levar minha máquina do tempo de volta a 2011 e descobrir isso
Blundell

324

Sim, podemos fazer isso usando Gson

Baixe o código de trabalho do GitHub

SharedPreferences mPrefs = getPreferences(MODE_PRIVATE);

Para salvar

Editor prefsEditor = mPrefs.edit();
Gson gson = new Gson();
String json = gson.toJson(myObject); // myObject - instance of MyObject
prefsEditor.putString("MyObject", json);
prefsEditor.commit();

Esqueço

Gson gson = new Gson();
String json = mPrefs.getString("MyObject", "");
MyObject obj = gson.fromJson(json, MyObject.class);

Update1

A versão mais recente do GSON pode ser baixada em github.com/google/gson .

Update2

Se você estiver usando o Gradle / Android Studio, basta colocar o seguinte na build.gradleseção de dependências -

implementation 'com.google.code.gson:gson:2.6.2'

não está funcionando no meu caso. Mesmo depois de colocar jar em libs e definir o caminho de construção, a classe Gson não foi resolvida.
Shirish Herwade

Limpe o projeto e tente @ShirishHerwade
Parag Chauhan

@parag que também não está funcionando. Você pode me dizer as etapas para usar esse jar para remover o erro acima. Porque eu adicionei com sucesso aquele jar na pasta libs e, em seguida, em "java build path" também tentei adicionar json de armazenamento externo em meu desktop
Shirish Herwade

7
Essa resposta seria ainda melhor se mencionasse também suas limitações. Que tipo de objeto podemos e não podemos armazenar e recuperar dessa maneira? Obviamente, isso não funcionará para todas as classes.
wvdz

3
String json = gson.toJson("MyObject");deve ser o objeto, não uma String.
Ahmed Hegazy

44

podemos usar Outputstream para enviar nosso objeto para a memória interna. E converta para string e salve de preferência. Por exemplo:

    mPrefs = getPreferences(MODE_PRIVATE);
    SharedPreferences.Editor ed = mPrefs.edit();
    ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();

    ObjectOutputStream objectOutput;
    try {
        objectOutput = new ObjectOutputStream(arrayOutputStream);
        objectOutput.writeObject(object);
        byte[] data = arrayOutputStream.toByteArray();
        objectOutput.close();
        arrayOutputStream.close();

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        Base64OutputStream b64 = new Base64OutputStream(out, Base64.DEFAULT);
        b64.write(data);
        b64.close();
        out.close();

        ed.putString(key, new String(out.toByteArray()));

        ed.commit();
    } catch (IOException e) {
        e.printStackTrace();
    }

quando precisamos extrair o objeto de preferência. Use o código abaixo

    byte[] bytes = mPrefs.getString(indexName, "{}").getBytes();
    if (bytes.length == 0) {
        return null;
    }
    ByteArrayInputStream byteArray = new ByteArrayInputStream(bytes);
    Base64InputStream base64InputStream = new Base64InputStream(byteArray, Base64.DEFAULT);
    ObjectInputStream in;
    in = new ObjectInputStream(base64InputStream);
    MyObject myObject = (MyObject) in.readObject();

Olá, sei que isso foi postado há algum tempo, mas tem certeza de que o código que possui para extrair o objeto armazenado está correto? Estou recebendo vários erros nas últimas 2 linhas reclamando sobre como os construtores explícitos precisam ser definidos em vez de simplesmente ter "new ObjectInputStream (byteArray)". Obrigado pela ajuda!
Wakka Wakka Wakka

Oi, de repente estou recebendo uma EOFException em in = new ObjectInputStream (base64InputStream); Estou escrevendo para preferências compartilhadas exatamente da mesma maneira que você. O que você acha que pode estar errado?
marienke

Você tem alguma exceção ao escrever Object to pref? Do SDK: Lançada EOFException quando um programa encontra o final de um arquivo ou fluxo durante uma operação de entrada.
Kislingk

Parabéns, essa é a melhor solução que encontrei para esse problema até agora. Sem dependências. No entanto, deve-se notar que para poder usar ObjectOutput / InputStream para um objeto, o referido objeto e todos os objetos personalizados dentro dele devem implementar a interface serializável.
user1112789

8

Eu tive o mesmo problema, aqui está minha solução:

Tenho a classe MyClass e ArrayList <MyClass> que desejo salvar nas Preferências compartilhadas. A princípio, adicionei um método a MyClass que o converte em objeto JSON:

public JSONObject getJSONObject() {
    JSONObject obj = new JSONObject();
    try {
        obj.put("id", this.id);
        obj.put("name", this.name);
    } catch (JSONException e) {
        e.printStackTrace();
    }
    return obj;
}

Então aqui está o método para salvar o objeto "ArrayList <MyClass> items":

SharedPreferences mPrefs = context.getSharedPreferences("some_name", 0);
    SharedPreferences.Editor editor = mPrefs.edit();

    Set<String> set= new HashSet<String>();
    for (int i = 0; i < items.size(); i++) {
        set.add(items.get(i).getJSONObject().toString());
    }

    editor.putStringSet("some_name", set);
    editor.commit();

E aqui está o método para recuperar o objeto:

public static ArrayList<MyClass> loadFromStorage() {
    SharedPreferences mPrefs = context.getSharedPreferences("some_name", 0);

    ArrayList<MyClass> items = new ArrayList<MyClass>();

    Set<String> set = mPrefs.getStringSet("some_name", null);
    if (set != null) {
        for (String s : set) {
            try {
                JSONObject jsonObject = new JSONObject(s);
                Long id = jsonObject.getLong("id"));
                String name = jsonObject.getString("name");
                MyClass myclass = new MyClass(id, name);

                items.add(myclass);

            } catch (JSONException e) {
                e.printStackTrace();
         }
    }
    return items;
}

Observe que StringSet em Preferências compartilhadas está disponível desde a API 11.


Resolveu meu problema. Eu quero adicionar algo. Para o primeiro uso, devemos verificar se o conjunto é nulo. if (set! = null) {for (String s: set) {..}}
xevser de

@xevser Eu adicionei verificação de nulos conforme sugerido. Obrigado.
Micer,

6

Usando a Biblioteca Gson:

dependencies {
compile 'com.google.code.gson:gson:2.8.2'
}

Loja:

Gson gson = new Gson();
//Your json response object value store in json object
JSONObject jsonObject = response.getJSONObject();
//Convert json object to string
String json = gson.toJson(jsonObject);
//Store in the sharedpreference
getPrefs().setUserJson(json);

Recuperar:

String json = getPrefs().getUserJson();

O pacote não é um mecanismo de serialização de uso geral. Esta classe (e a API Parcelable correspondente para colocar objetos arbitrários em um Parcel) é projetada como um transporte IPC de alto desempenho. Como tal, não é apropriado colocar quaisquer dados do Parcel no armazenamento persistente: as alterações na implementação subjacente de qualquer um dos dados do Parcel podem tornar os dados mais antigos ilegíveis.
Marcos Vasconcelos

1

Você pode fazer isso usando a PowerPreferencebiblioteca em 3 etapas fáceis!

https://github.com/AliAsadi/PowerPreference

1. Criar objeto

Object obj = new Object();

2. Escreva de acordo com a preferência compartilhada

PowerPreference.getDefaultFile().put("object",obj);

3. Obtendo o objeto

Object obj = PowerPreference.getDefaultFile()
                            .getObject("object", Object.class);

0

Usando este objeto -> TinyDB - Android-Shared-Preferences-Turbo é muito simples. você pode salvar a maioria dos objetos comumente usados ​​com ele, como matrizes, inteiros, listas de strings, etc.


Legal, mas acho que isso funciona apenas para tipos primitivos (String, double, int, etc) e não para objetos personalizados (POJOS)
CommonSenseCode

agora funciona para objetos personalizados, verifique o Leia-me, ele foi atualizado
kc ochibili

0

Você pode usar a biblioteca Complex Preferences Android - de Felipe Silvestre para armazenar seus objetos personalizados. Basicamente, ele está usando o mecanismo GSON para armazenar objetos.

Para salvar o objeto em preferências:

User user = new User();
user.setName("Felipe");
user.setAge(22); 
user.setActive(true); 

ComplexPreferences complexPreferences = ComplexPreferences.getComplexPreferences(
     this, "mypref", MODE_PRIVATE);
complexPreferences.putObject("user", user);
complexPreferences.commit();

E para recuperá-lo:

ComplexPreferences complexPreferences = ComplexPreferences.getComplexPreferences(this, "mypref", MODE_PRIVATE);
User user = complexPreferences.getObject("user", User.class);

O pacote não é um mecanismo de serialização de uso geral. Esta classe (e a API Parcelable correspondente para colocar objetos arbitrários em um Parcel) é projetada como um transporte IPC de alto desempenho. Como tal, não é apropriado colocar quaisquer dados do Parcel no armazenamento persistente: as alterações na implementação subjacente de qualquer um dos dados do Parcel podem tornar os dados mais antigos ilegíveis.
Marcos Vasconcelos

Esta é obsoleto
IgorGanapolsky

0

Você pode usar GSON, usando Gradle Build.gradle:

implementation 'com.google.code.gson:gson:2.8.0'

Então, em seu código, por exemplo, pares de string / booleano com Kotlin:

        val nestedData = HashMap<String,Boolean>()
        for (i in 0..29) {
            nestedData.put(i.toString(), true)
        }
        val gson = Gson()
        val jsonFromMap = gson.toJson(nestedData)

Adicionando a SharedPrefs:

        val sharedPrefEditor = context.getSharedPreferences(_prefName, Context.MODE_PRIVATE).edit()
        sharedPrefEditor.putString("sig_types", jsonFromMap)
        sharedPrefEditor.apply()

Agora, para recuperar os dados:

val gson = Gson()
val sharedPref: SharedPreferences = context.getSharedPreferences(_prefName, Context.MODE_PRIVATE)
val json = sharedPref.getString("sig_types", "false")
val type = object : TypeToken<Map<String, Boolean>>() {}.type
val map = gson.fromJson(json, type) as LinkedTreeMap<String,Boolean>
for (key in map.keys) {
     Log.i("myvalues", key.toString() + map.get(key).toString())
}

O pacote não é um mecanismo de serialização de uso geral. Esta classe (e a API Parcelable correspondente para colocar objetos arbitrários em um Parcel) é projetada como um transporte IPC de alto desempenho. Como tal, não é apropriado colocar quaisquer dados do Parcel no armazenamento persistente: as alterações na implementação subjacente de qualquer um dos dados do Parcel podem tornar os dados mais antigos ilegíveis.
Marcos Vasconcelos

0

Preferência comum compartilhada (CURD) SharedPreference: para armazenar dados na forma de pares de valor-chave com uma classe Kotlin simples.

var sp = SharedPreference(this);

Armazenamento de dados:

Para armazenar dados String, Int e Boolean, temos três métodos com o mesmo nome e parâmetros diferentes (Sobrecarga de método).

save("key-name1","string value")
save("key-name2",int value)
save("key-name3",boolean)

Recuperar dados: Para recuperar os dados armazenados em SharedPreferences, use os seguintes métodos.

sp.getValueString("user_name")
sp.getValueInt("user_id")
sp.getValueBoolean("user_session",true)

Limpar todos os dados: para limpar todas as SharedPreferences, use o código a seguir.

 sp.clearSharedPreference()

Remova dados específicos:

sp.removeValue("user_name")

Classe de preferência compartilhada comum

import android.content.Context
import android.content.SharedPreferences

class SharedPreference(private val context: Context) {
    private val PREFS_NAME = "coredata"
    private val sharedPref: SharedPreferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
    //********************************************************************************************** save all
    //To Store String data
    fun save(KEY_NAME: String, text: String) {

        val editor: SharedPreferences.Editor = sharedPref.edit()
        editor.putString(KEY_NAME, text)
        editor.apply()
    }
    //..............................................................................................
    //To Store Int data
    fun save(KEY_NAME: String, value: Int) {

        val editor: SharedPreferences.Editor = sharedPref.edit()
        editor.putInt(KEY_NAME, value)
        editor.apply()
    }
    //..............................................................................................
    //To Store Boolean data
    fun save(KEY_NAME: String, status: Boolean) {

        val editor: SharedPreferences.Editor = sharedPref.edit()
        editor.putBoolean(KEY_NAME, status)
        editor.apply()
    }
    //********************************************************************************************** retrieve selected
    //To Retrieve String
    fun getValueString(KEY_NAME: String): String? {

        return sharedPref.getString(KEY_NAME, "")
    }
    //..............................................................................................
    //To Retrieve Int
    fun getValueInt(KEY_NAME: String): Int {

        return sharedPref.getInt(KEY_NAME, 0)
    }
    //..............................................................................................
    // To Retrieve Boolean
    fun getValueBoolean(KEY_NAME: String, defaultValue: Boolean): Boolean {

        return sharedPref.getBoolean(KEY_NAME, defaultValue)
    }
    //********************************************************************************************** delete all
    // To clear all data
    fun clearSharedPreference() {

        val editor: SharedPreferences.Editor = sharedPref.edit()
        editor.clear()
        editor.apply()
    }
    //********************************************************************************************** delete selected
    // To remove a specific data
    fun removeValue(KEY_NAME: String) {
        val editor: SharedPreferences.Editor = sharedPref.edit()
        editor.remove(KEY_NAME)
        editor.apply()
    }
}

Blog: https://androidkeynotes.blogspot.com/2020/02/shared-preference.html


-2

Não há como armazenar objetos em SharedPreferences. O que fiz foi criar uma classe pública, colocar todos os parâmetros que preciso e criar setters e getters, consegui acessar meus objetos,


-3

Você precisa recuperar o objeto mesmo após o aplicativo fechar o donw ou apenas durante sua execução?

Você pode armazená-lo em um banco de dados.
Ou simplesmente crie uma classe de aplicativo personalizada.

public class MyApplication extends Application {

    private static Object mMyObject;
    // static getter & setter
    ...
}

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application ... android:name=".MyApplication">
        <activity ... />
        ...
    </application>
    ...
</manifest>

E então, em todas as atividades, faça:

((MyApplication) getApplication).getMyObject();

Não é realmente a melhor maneira, mas funciona.


-6

Sim. Você pode armazenar e recuperar o objeto usando Sharedpreference

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.