我想在共享偏好设置中保存自定义对象myObject
。此自定义对象的位置为ArrayList<anotherCustomObj>
。此anotherCustomObj
包含主要变量。
myObject
和anotherCustomObj
都是可以分配的。
我尝试使用以下代码将其转换为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<RS_SingleMatch> CREATOR = new Parcelable.Creator<RS_SingleMatch>() {
@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) < dob.get(Calendar.DAY_OF_YEAR)) {
age--;
}
} catch (ParseException e) {
e.printStackTrace();
}
return age;
}
// Download image if not available
protected void downloadAndSaveImage() {
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(this.context);
String imagePath = prefs.getString(IMAGE_PATH + getUserId(), "");
File file = new File(imagePath);
// If image path not stored in user defaults or image does not exists
// then
if ((imagePath == null || !file.exists()) && this.imageUrl.length() > 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;
}
}
答案 0 :(得分:2)
达米安发布的链接有助于解决我的问题。但是,在我的情况下,自定义对象中没有视图组件。
根据我的观察,如果你找到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);