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

时间:2013-10-10 12:58:18

标签: java android sharedpreferences gson

我想在共享偏好设置中保存自定义对象myObject。此自定义对象的位置为ArrayList<anotherCustomObj>。此anotherCustomObj包含主要变量。

myObjectanotherCustomObj都是可以分配的。

我尝试使用以下代码将其转换为String并保存:

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

但它给出了RunTimeException。

编辑:以下是logcat屏幕截图。 enter image description here

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

1 个答案:

答案 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);