在共享首选项中保存自定义对象

我想在共享首选项中保存自定义对象myObject 。 此自定义对象具有ArrayList 。 这个anotherCustomObj有主要变量。

myObjectanotherCustomObj都是可以分配的。

我尝试下面的代码将其转换为String并保存:

 String myStr = gson.toJson(myObject); editor.putString(MY_OBJ, myStr); 

但它给出了RunTimeException。

编辑:下面是logcat屏幕截图。 在此处输入图像描述

anotherCustomObj实现:

 package com.objectlounge.ridesharebuddy.classes; import java.io.File; import java.io.InputStream; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.Locale; import android.annotation.SuppressLint; import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Parcel; import android.os.Parcelable; import android.preference.PreferenceManager; import android.util.Log; import com.google.gson.annotations.SerializedName; import com.objectlounge.ridesharebuddy.R; public class RS_SingleMatch implements Parcelable { private static final String RIDESHARE_DIRECTORY = "RideShareBuddy"; private static final String TAG = "RS_SingleMatch"; private static final String IMAGE_PATH = "imagePath"; private static final String IMAGE_NAME_PREFIX = "RideShareBuddyUserImage"; private Context context; @SerializedName("id") private int userId; private int tripId; private String imageUrl; @SerializedName("userName") private String email; private String realName; private String gender; private int reputation; private String createdAt; private String birthdate; private float fromLat, fromLon, toLat, toLon; private String fromPOI, toPOI; private String departureTime; private int matchStrength; // Constructor public RS_SingleMatch(Context context) { this.context = context; } // Constructor to use when reconstructing an object from a parcel public RS_SingleMatch(Parcel in) { readFromParcel(in); } @Override public int describeContents() { return 0; } @Override // Called to write all variables to a parcel public void writeToParcel(Parcel dest, int flags) { dest.writeInt(userId); dest.writeInt(tripId); dest.writeString(imageUrl); dest.writeString(email); dest.writeString(realName); dest.writeString(gender); dest.writeInt(reputation); dest.writeString(createdAt); dest.writeString(birthdate); dest.writeFloat(fromLat); dest.writeFloat(fromLon); dest.writeFloat(toLat); dest.writeFloat(toLon); dest.writeString(fromPOI); dest.writeString(toPOI); dest.writeString(departureTime); dest.writeInt(matchStrength); } // Called from constructor to read object properties from parcel private void readFromParcel(Parcel in) { // Read all variables from parcel to created object userId = in.readInt(); tripId = in.readInt(); imageUrl = in.readString(); email = in.readString(); realName = in.readString(); gender = in.readString(); reputation = in.readInt(); createdAt = in.readString(); birthdate = in.readString(); fromLat = in.readFloat(); fromLon = in.readFloat(); toLat = in.readFloat(); toLon = in.readFloat(); fromPOI = in.readString(); toPOI = in.readString(); departureTime = in.readString(); matchStrength = in.readInt(); } // This creator is used to create new object or array of objects public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { @Override public RS_SingleMatch createFromParcel(Parcel in) { return new RS_SingleMatch(in); } @Override public RS_SingleMatch[] newArray(int size) { return new RS_SingleMatch[size]; } }; // Getters public int getUserId() { return userId; } public int getTripId() { return tripId; } public String getImageUrl() { return imageUrl; } public Bitmap getImage() { Bitmap image = null; // If imageUrl is not empty if (getImageUrl().length() > 0) { SharedPreferences prefs = PreferenceManager .getDefaultSharedPreferences(this.context); String imagePath = prefs.getString(IMAGE_PATH + getUserId(), ""); // Get image from cache if ((image = RS_FileOperationsHelper.getImageAtPath(imagePath)) == null) { Log.d(TAG, "Image not found on disk."); Thread t = new Thread(new Runnable() { @Override public void run() { // If image not found on storage then download it setImage(downloadImage(getImageUrl())); } }); t.start(); } } else { // Use default image image = getDefaultProfileImage(); } image = RS_ImageViewHelper.getRoundededImage(image, image.getWidth()); Log.d(TAG, "Image width : " + image.getWidth()); return image; } public String getEmail() { return email; } public String getRealName() { return realName; } public String getGender() { return gender; } public int getReputation() { return reputation; } public String getCreatedAt() { return createdAt; } public String getBirthdate() { return birthdate; } public float getFromLat() { return fromLat; } public float getFromLon() { return fromLon; } public float getToLat() { return toLat; } public float getToLon() { return toLon; } public String getFromPOI() { return fromPOI; } public String getToPOI() { return toPOI; } public String getDepartureTime() { return departureTime; } public int getMatchStrength() { return matchStrength; } // Setters public void setContext(Context context) { this.context = context; } public void setUserId(int userId) { this.userId = userId; } public void setTripId(int tripId) { this.tripId = tripId; } public void setImageUrl(String imageUrl) { this.imageUrl = imageUrl; } public void setImage(Bitmap img) { if (img != null) { // Get cache directory's path and append RIDESHARE_DIRECTORY. String cacheDirStoragePath = context.getCacheDir() + "/" + RIDESHARE_DIRECTORY; // Create directory at cacheDirStoragePath if does not exist. if (RS_FileOperationsHelper .createDirectoryAtPath(cacheDirStoragePath)) { String imagePath = cacheDirStoragePath + "/" + IMAGE_NAME_PREFIX + this.userId + ".png"; // Save new image to cache RS_FileOperationsHelper.saveImageAtPath(img, imagePath, this.context); SharedPreferences pref = PreferenceManager .getDefaultSharedPreferences(context); Editor e = pref.edit(); e.putString(IMAGE_PATH + getUserId(), imagePath); e.commit(); } } } public void setEmail(String email) { this.email = email; } public void setRealName(String realName) { this.realName = realName; } public void setGender(String gender) { this.gender = gender; } public void setReputation(int reputation) { this.reputation = reputation; } public void setCreatedAt(String createdAt) { this.createdAt = createdAt; } public void setBirthdate(String birthdate) { this.birthdate = birthdate; } public void setFromLat(float fromLat) { this.fromLat = fromLat; } public void setFromLon(float fromLon) { this.fromLon = fromLon; } public void setToLat(float toLat) { this.toLat = toLat; } public void setToLon(float toLon) { this.toLon = toLon; } public void setFromPOI(String fromPOI) { this.fromPOI = fromPOI; } public void setToPOI(String toPOI) { this.toPOI = toPOI; } public void setDepartureTime(String departureTime) { this.departureTime = departureTime; } public void setMatchStrength(int matchStrength) { this.matchStrength = matchStrength; } // calculates age using given date @SuppressLint("SimpleDateFormat") public int calculateAge(String date) { int age = 0; try { SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); Date bdate = formatter.parse(date); Calendar lCal = Calendar.getInstance(); lCal.setTime(bdate); int lYear = lCal.get(Calendar.YEAR); int lMonth = lCal.get(Calendar.MONTH) + 1; int lDay = lCal.get(Calendar.DATE); Calendar dob = Calendar.getInstance(); Calendar today = Calendar.getInstance(); dob.set(lYear, lMonth, lDay); age = today.get(Calendar.YEAR) - dob.get(Calendar.YEAR); if (today.get(Calendar.DAY_OF_YEAR)  0) { // Download on separate thread Thread t = new Thread(new Runnable() { @Override public void run() { setImage(downloadImage(getImageUrl())); } }); t.start(); } } // Download an image private Bitmap downloadImage(String imageUrl) { Log.d(TAG, "Image url : " + imageUrl); Bitmap image = null; try { // Download an image from url InputStream in = new java.net.URL(imageUrl.trim()).openStream(); image = BitmapFactory.decodeStream(in); } catch (Exception e) { e.printStackTrace(); } Log.d(TAG, "Image downloading complete. image : " + image); return image; } // Get default image protected Bitmap getDefaultProfileImage() { Bitmap image = BitmapFactory.decodeResource( this.context.getResources(), R.drawable.default_male); if (this.gender.toUpperCase(Locale.US).startsWith("F")) { image = BitmapFactory.decodeResource(this.context.getResources(), R.drawable.default_female); } return image; } } 

由damian发布的链接有助于解决我的问题。 但是,在我的情况下,自定义对象中没有视图组件。

根据我的观察,如果你找到multiple JSON fields for ANY_VARIABLE_NAME ,那很可能是因为GSON无法转换对象。 你可以尝试下面的代码来解决它。

添加以下类以告诉GSON仅保存和/或检索声明了序列化名称的变量。

 class Exclude implements ExclusionStrategy { @Override public boolean shouldSkipClass(Class arg0) { // TODO Auto-generated method stub return false; } @Override public boolean shouldSkipField(FieldAttributes field) { SerializedName ns = field.getAnnotation(SerializedName.class); if(ns != null) return false; return true; } } 

下面是您需要保存/检索其对象的类。 为需要保存和/或检索的变量添加@SerializedName

 class myClass { @SerializedName("id") int id; @SerializedName("name") String name; } 

将myObject转换为jsonString的代码:

 Exclude ex = new Exclude(); Gson gson = new GsonBuilder().addDeserializationExclusionStrategy(ex).addSerializationExclusionStrategy(ex).create(); String jsonString = gson.toJson(myObject); 

从jsonString获取对象的代码:

 Exclude ex = new Exclude(); Gson gson = new GsonBuilder().addDeserializationExclusionStrategy(ex).addSerializationExclusionStrategy(ex).create(); myClass myObject = gson.fromJson(jsonString, myClass.class);