1
我试图用Gson保存一个序列化/反序列化POJOS列表。虽然一般情况下这是没有这样一个特殊的任务,我发现了一个例外,我以前从来没见过:Gson和方向变化的问题
01-11 14:17:22.556: E/AndroidRuntime(15941): java.lang.RuntimeException:
Unable to start activity ComponentInfo{com.timkranen.playpalproject/com.timkranen.playpalproject.HomeActivity}:
java.lang.RuntimeException: Unable to invoke no-args constructor for interface java.util.concurrent.locks.Lock.
Register an InstanceCreator with Gson for this type may fix this problem.
我怀疑它与事实列表项正在事加载到AsyncTask中。任何人都有这个问题的经验?
我试着把我在onSaveInstanceState内执行的逻辑(用于保存)放在同步方法中,但是没有帮助。
编辑
下面是我的一些代码,试图使之更加清晰。我有一个名为friendsList的列表。列表填充这个的AsyncTask和onCreateView()被执行
private class RetrieveFriends extends AsyncTask<Void, Integer, String> {
@Override
protected String doInBackground(Void... params) {
// get friends
if (friendProfiles == null || friendProfiles.size() == 0) {
friendProfiles = new ArrayList<Profile>();
if (currentProfile.getFriendUids() != null
&& currentProfile.getFriendUids().size() > 0)
for (String fUid : currentProfile.getFriendUids()) {
Profile friend = ProfileDataManager
.getProfileFromId(fUid);
friendProfiles.add(friend);
}
if (friendProfiles.size() == 0) {
return "null";
}
}
return "notnull";
}
@Override
protected void onPostExecute(String result) {
if (!result.equals("null")) {
loadingFriendsBar.setVisibility(View.INVISIBLE);
friendsList.setVisibility(View.VISIBLE);
FriendListAdapter adapter = new FriendListAdapter(
containedActivity, R.layout.friendslist_row,
friendProfiles);
friendsList.setAdapter(adapter);
} else {
loadingFriendsBar.setVisibility(View.INVISIBLE);
friendMsg.setVisibility(View.VISIBLE);
}
}
}
现在在的onSaveInstanceState我序列化列表以JSON是这样的:
private synchronized void saveToState(Bundle state) {
Gson gson = new Gson();
Type listOfProfiles = new TypeToken<List<Profile>>() {
}.getType();
String json = gson.toJson(friendProfiles, listOfProfiles);
state.putString("json_friendProfiles", json);
}
该方法是直接的onSaveInstanceState(叫) 。检索它是相同的:
private synchronized void retrieveFromState(String json) {
Type listOfProfiles = new TypeToken<List<Profile>>() {
}.getType();
Gson gson = new Gson();
friendProfiles = (List<Profile>) gson.fromJson(json,
listOfProfiles);
}
奇怪的是,状态正确保存时导航到不同的片段。只有当我改变方向时才会出现错误。
编辑:根据要求,这里的Profile类
public class Profile {
private String mEmail;
private String mPassword;
private String uid;
// optional properties
private String name;
private String location;
private String about;
private ParseFile image; // not certain of data type
private List<String> friendUids;
public String getName() {
if (name == null || name.equals("")) {
return "Name unknown";
}
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLocation() {
if (location == null || location.equals("")) {
return "Location unknown";
}
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getAbout() {
if (about == null || about.equals("")) {
return "About unknown";
}
return about;
}
public void setAbout(String about) {
this.about = about;
}
public void setUid(String Uid) {
this.uid = Uid;
}
public String getUid() {
return this.uid;
}
public String getPassword() {
return mPassword;
}
public String getEmail() {
return mEmail;
}
public Profile(String email, String password) {
this.mEmail = email;
this.mPassword = password;
}
/*
* Saves a Profile and returns the profiles UID This is ONLY APPLICABLE for
* NEW profiles use the update method to update existing profile data
*/
public void saveToParse(SaveCallback saveCallBack) {
if (ProfileDataManager.IsRegistered(this) != true) {
ParseObject pObject = new ParseObject("Profiles");
pObject.put("email", this.mEmail);
pObject.put("password", this.mPassword);
pObject.saveInBackground(saveCallBack);
} else {
saveCallBack.done(new ParseException(ErrorCodes.ALREADY_REGISTERED,
"AlreadyRegistered"));
}
}
public void update() {
ParseQuery<ParseObject> query = ParseQuery.getQuery("Profiles");
query.getInBackground(this.uid, new GetCallback<ParseObject>() {
@Override
public void done(ParseObject object, ParseException e) {
if (e == null) {
// update the object
object.put("email", Profile.this.mEmail);
object.put("password", Profile.this.mPassword);
if (Profile.this.name != null) {
object.put("name", Profile.this.name);
}
if (Profile.this.location != null) {
object.put("location", Profile.this.location);
}
if (Profile.this.about != null) {
object.put("about", Profile.this.about);
}
if (Profile.this.image != null) {
object.put("profileImage", Profile.this.image);
}
if (Profile.this.friendUids != null
&& Profile.this.friendUids.size() != 0) {
object.put("friends", Profile.this.friendUids);
}
object.saveInBackground();
}
}
});
}
/*
* Use updateWithCallBack when you want to update an object but want to show
* the updated data immediatly using a callback, when calling this method
* make sure that currentProfile in HomeActivity is set to the new Profile!
*/
public void updateWithCallBack(final SaveCallback callBack) {
ParseQuery<ParseObject> query = ParseQuery.getQuery("Profiles");
query.getInBackground(this.uid, new GetCallback<ParseObject>() {
@Override
public void done(ParseObject object, ParseException e) {
if (e == null) {
// update the object
object.put("email", Profile.this.mEmail);
object.put("password", Profile.this.mPassword);
if (Profile.this.name != null) {
object.put("name", Profile.this.name);
}
if (Profile.this.location != null) {
object.put("location", Profile.this.location);
}
if (Profile.this.about != null) {
object.put("about", Profile.this.about);
}
if (Profile.this.image != null) {
object.put("profileImage", Profile.this.image);
}
if (Profile.this.friendUids != null
&& Profile.this.friendUids.size() != 0) {
object.put("friends", Profile.this.friendUids);
}
object.saveInBackground(callBack);
}
}
});
}
// retrieves the image, when done calls callback
public void retrieveProfileImage(GetDataCallback callBack) {
this.image.getDataInBackground(callBack);
}
public ParseFile getProfileImage() {
return this.image;
}
public void setProfileImage(ParseFile image) {
this.image = image;
}
public void saveProfileImage(Bitmap image) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 50, stream);
byte[] byteArray = stream.toByteArray();
String imgid = this.getUid() + "_profile_image.jpeg";
String fileNameForImage = this.getUid() + "_profile_image.jpeg";
this.image = new ParseFile(fileNameForImage, byteArray);
}
public List<String> getFriendUids() {
return this.friendUids;
}
public void addFriend(String uid) {
if (this.friendUids != null) {
friendUids.add(uid);
} else {
friendUids = new ArrayList<String>();
friendUids.add(uid);
}
}
public void setFriends(Object friends) {
ArrayList<String> f = (ArrayList<String>) friends;
this.friendUids = f;
}
}
你能告诉我们你的代码吗? –
如果不需要,请写下您的应用程序,以便在方向更改时不重新创建活动。 – tolgap
我编辑了我原来的问题。 @tolgap但是这不是很糟糕的做法吗?我不认为我需要它,但是像这样实施它是否安全? –