我想保存一个自定义对象myObject在共享首选项中。此自定义对象的位置 ArrayList<anotherCustomObj> .这anotherCustomObj有主要变量。
两者都是 myObject和 anotherCustomObj可打包。
我尝试使用下面的代码将其转换为字符串并保存:
String myStr = gson.toJson(myObject);
editor.putString(MY_OBJ, myStr);
但它给出了 RunTimeException。
编辑: 下面是 logcat 屏幕截图。
另一个 CustomObj 实现:
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;
}
}
最佳答案
damian 发布的链接有助于解决我的问题。但是,在我的例子中,自定义对象中没有 View 组件。
根据我的观察,如果您发现 ANY_VARIABLE_NAME 有多个 JSON 字段,那么很可能是因为 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);
关于java - 在共享首选项中保存自定义对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19296404/
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
我正在尝试设置一个puppet节点,但rubygems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由rubygems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby
在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev
我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer
我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss
我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢
我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby1.9+ 关于ruby-主要:Objectwhenrun
好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信
我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象