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.

androidGuy
fonte
Adiciono
Tsung Goh
Aqui está um exemplo thegeekyland.blogspot.com/2015/11/…
Arlind
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?

Blundell
fonte
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'
Parag Chauhan
fonte
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();
Kislingk
fonte
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.

Micer
fonte
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();
Ramesh sambu
fonte
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);
Ali Asadi
fonte
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.

kc ochibili
fonte
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);
Serhii Hrabas
fonte
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())
}
CAZ
fonte
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

Hari Shankar S
fonte
-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,

Ismael Ozil
fonte
-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.

luc.chante
fonte
-6

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

Sukanya
fonte