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

时间:2016-04-27 07:57:45

标签: android gson sharedpreferences adapter

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

要添加的代码:

    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();
            }
        }
    });

从其他活动中退回的代码:

     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,干杯!

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

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);
    }

谢谢!

1 个答案:

答案 0 :(得分:1)

例如,作为一个过于简化的应用程序,您可以按如下方式定义自定义类(当然,您必须根据自己的细节进行调整)。概念是创建一个自定义对象数组,将其转换为json,存储它。一旦你看到它,它就非常简单。

代码

{ "a", "aba", "abacaba", "acaba", "ba", "bacaba", "caba" }

注释

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

假设

为了实现这一点,我假设您有一个名为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+"]"; } } 而不是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; } } 并创建布局(仅包含两个带有给定ID的文本视图),您将获得以下结果。您可以尝试删除第一次运行后创建数据的部分,只留下获取数据的部分,以确保数据保持不变。

enter image description here