android - 无法在 SharedPreferences 中保存多个自定义对象?

标签 android gson sharedpreferences adapter

这是我的问题。我可以保存一个对象,但如果我保存另一个对象,它将删除前一个项目。我正在使用 gson lib 来保存我的项目。经过一些研究,我看到了这个 How to use SharedPreferences to save more than one values? 但由于我的自定义对象,我不能使用它,如果我使用 .toString(),我将无法取回我的原始项目。我知道这是用于保存对象的相同 key ,它将删除前一个对象,但我真的不知道每次保存项目时如何提供不同的 key 。

要添加的代码:

    addFav.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {

            if (currentProduit.getIsAdded() ==0) {
                SharedPreferences.Editor prefsEditor = mPrefs.edit();
                Gson gson = new Gson();
                String myJson = gson.toJson(currentProduit);
                Log.i("INFO", "Value of saved data" + myJson);
                prefsEditor.putString("myproduct", myJson);
                prefsEditor.apply();
                Toast.makeText(getApplicationContext(), "Data saved !", Toast.LENGTH_SHORT).show();
                addFav.setText(R.string.delete_fav);
                currentProduit.setIsAdded(1);
            } else {
                addFav.setText(R.string.add_fav);
                currentProduit.setIsAdded(0);
                SharedPreferences.Editor editor = mPrefs.edit();
                editor.remove("myproduct").apply();
                Toast.makeText(getApplicationContext(), "Data removed !", Toast.LENGTH_SHORT).show();
            }
        }
    });

从其他 Activity 中恢复的代码:

     String myJson = mPrefs.getString("myproduct", "");
    Log.i("INFO", "Value of loaded data" + myJson);

    if (myJson.isEmpty() && favProductList.isEmpty()) {
        listview_R.setAdapter(null);
        Log.i("INFO", "No items");
        title.setText(getString(R.string.fav));
    } else if (myJson.isEmpty() && favProductList != null) {
        myCustomAdapterVersionR = new CustomAdapter_VersionR(getApplicationContext(), favProductList);
        listview_R.setAdapter(myCustomAdapterVersionR);
    } else {
        Product savedProduct = gson.fromJson(myJson, Product.class);
        favProductList.add(savedProduct);
        Log.i("INFO", "Favorite was added");
        myCustomAdapterVersionR = new CustomAdapter_VersionR(getApplicationContext(), favProductList);
        listview_R.setAdapter(myCustomAdapterVersionR);
    }

感谢您的帮助!顺便说一句,因为它没有保存很多项目,所以我没有使用 sqlite db,干杯!

编辑:我尝试了 Juan Cortés 的解决方案,但在取回共享首选项后出现此错误 --> 错误:不兼容的类型:CustomProduct[] 无法转换为列表,这是代码

if (fromPrefs.isEmpty() && favProductList.isEmpty()) {
        listview_R.setAdapter(null);
        Log.i("INFO", "No items");
        title.setText(getString(R.string.fav));
    } else {
        //Product savedProduct = gson.fromJson(fromPrefs, Product.class);
        //favProductList.add(savedProduct);
        //Get the Object array back from the String `fromPrefs`
        CustomProduct[] reInflated = gson.fromJson(fromPrefs,CustomProduct[].class);
        Log.i("INFO", "Favorite was added");
        myCustomAdapterVersionR = new CustomAdapter_VersionR(getApplicationContext(), reInflated); //error
        listview_R.setAdapter(myCustomAdapterVersionR);
    }

谢谢!

最佳答案

例如,作为一个过度简化的应用程序,您可以定义一个自定义类如下(当然,您必须根据自己的具体情况对其进行调整)。这个概念是创建一个自定义对象数组,将其转换为 json,然后存储。一旦您看到它,它真的很简单。

代码

Gson gson = new Gson();

//Create an array to work with it, dummy content
CustomProduct[] exampleList = new CustomProduct[10];
for(int i=0;i<10;i++){
    exampleList[i] = new CustomProduct("string","number:"+i);
}

//Get a String representation of the objects
String forStoring = gson.toJson(exampleList);

//HERE you can store and retrieve to SharedPreferences
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.edit().putString("myarrayofcustomobjects", forStoring).commit();

//Get the string back from the SharedPreferences
String fromPrefs = prefs.getString("myarrayofcustomobjects","");

//Get the Object array back from the String `fromPrefs`
CustomProduct[] reInflated = gson.fromJson(fromPrefs,CustomProduct[].class);

注意事项

如果数组中已经有一组对象,则需要如上所示扩充数组,用这些元素+要添加的元素创建一个新数组,再次将它们转换为字符串,然后存储它们。一旦这变得太麻烦,您将转向另一种方法来为您的应用程序保留数据,但只要没有那么多,就应该没问题。

假设

为了让它工作,我假设您有一个名为 CustomProduct 的自定义对象,其定义如下:

public class CustomProduct {
    String field1,field2;
    public CustomProduct(String field1, String field2){
        super();
        this.field1 = field1;
        this.field2 = field2;
    }
    @Override
    public String toString() {
        return "CustomProduct [field1="+field1+",field2="+field2+"]";
    }
}

更新

用户想要在 ListView 中显示结果。您可以像下面这样定义自定义适配器以使其工作。现在是我建议您尽快转向 RecyclerView 而不是 ListView 的时候了,但首先要解决您遇到的问题,让它发挥作用,然后再对其进行改进

public class CustomAdapter extends BaseAdapter{
    private CustomProduct[] mProducts;
    private LayoutInflater mInflater;

    public CustomAdapter(Context context, CustomProduct[] products){
        mProducts = products;
        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }
    public int getCount() {
        return mProducts.length;
    }
    public CustomProduct getItem(int i) {
        return mProducts[i];
    }
    public long getItemId(int i) {
        return i;
    }
    public View getView(int i, View convertView, ViewGroup parent) {
        //Purposely not doing view recycling for sake of clarity
        View row = mInflater.inflate(R.layout.custom_row,parent,false);
        //Set the data from the row
        ((TextView)row.findViewById(R.id.field1)).setText(getItem(i).field1);
        ((TextView)row.findViewById(R.id.field2)).setText(getItem(i).field2);
        //Return the view
        return row;
    }
}

通过将此适配器设置为您的 ListView 并创建布局(它只包含两个具有给定 ID 的 TextView ),您将获得以下结果。您可以尝试在第一次运行后删除它创建数据的部分,只保留它获取数据的部分以确保它持久化。

enter image description here

关于android - 无法在 SharedPreferences 中保存多个自定义对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36883734/

相关文章:

java - Android Studio中调用jar库

java - spring webflux 所有 api 都给出 UnsupportedMediaTypeException

jaxb - 在 Jersey 使用 Gson 而不是 Jackson

android - 重新安装后应用程序可以播放

java - 使用 sharedPreferences 的 onPause 和 onResume 方法

Android onSharedPreferenceChanged 在提交完成之前触发

android - 使用 In App Billing 将付费的 Android 应用程序更改为免费的 - 现有客户不再需要

android - 如何解决android中双击按钮问题?

android - 更新 Firestore 中的文档

android - 使用 GSON 读取 JSON 数据