Gson和方向更改的问题

时间:2014-01-11 13:20:07

标签: java android concurrency gson

我正在尝试使用Gson保存序列化/反序列化POJOS列表。虽然通常这不是一项特殊的任务,但我得到了一个我以前从未见过的例外:

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中加载List项的事实有关。有人有这方面的经验吗?

我已经尝试将我在onSaveInstanceState中执行的逻辑(用于保存)放在同步方法中,但这没有帮助。

修改

这是我的一些代码,试图让它更清晰。我有一个名为friendsList的List。 List填入此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中,我将List序列化为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);
}

奇怪的是,导航到不同的片段时状态被正确保存。只有在我更改方向时才会出现错误。

编辑:根据要求,这里是个人资料类

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

}

1 个答案:

答案 0 :(得分:1)

Gson对象

private Gson gson = new GsonBuilder().
        setExclusionStrategies(new ParseExclusion()).
        create();

排除类

private class ParseExclusion implements ExclusionStrategy {

    public boolean shouldSkipClass(Class<?> arg0) {
        return false;
    }

    public boolean shouldSkipField(FieldAttributes f) {
        return (f.getDeclaredClass() == Lock.class);
    }

}

最后:

Type type = new TypeToken<List<Profile>>() {}.getType();
List<Profile>) friendProfiles = new ArrayList<Profile>();
friendProfiles = gson.fromJson(json,type);