简体   繁体   English

Gson和方向改变的问题

[英]Problems with Gson and orientation changes

I'm trying to save a serialize/deserialize a List of POJOS with Gson. 我正在尝试使用Gson保存序列化/反序列化POJOS列表。 While normally this isn't such a special task, I'm getting an exception that I've never seen before: 虽然通常这不是什么特别的任务,但我遇到了一个我从未见过的异常​​:

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.

I'm suspecting that it has something to with the fact that the List items are being loaded in an AsyncTask. 我怀疑这与List项正在AsyncTask中加载有关。 Anyone have experience with this problem? 任何人都有这个问题的经验吗?

I've tried putting the logic that I execute within onSaveInstanceState (for saving) in a synchronized method, but that didn't help. 我尝试将执行的逻辑放在onSaveInstanceState(用于保存)中的同步方法中,但这无济于事。

Edit 编辑

Here's some of my code to try and make it more clear. 这是我的一些代码,试图使其更加清晰。 I've got a List that is called friendsList. 我有一个名为friendsList的列表。 The List is filled in this AsyncTask and is executed in onCreateView() 该列表填充在此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);
        }
    }

}

Now in the onSaveInstanceState I serialize that List to JSON like this: 现在,在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);
}

That method is called directly in onSaveInstanceState(). 该方法直接在onSaveInstanceState()中调用。 Retrieving it is the same: 检索相同:

private synchronized void retrieveFromState(String json) {
    Type listOfProfiles = new TypeToken<List<Profile>>() {
    }.getType();
    Gson gson = new Gson();
    friendProfiles = (List<Profile>) gson.fromJson(json,
            listOfProfiles);
}

The weird thing is, the state is correctly saved when navigating to a different Fragment. 奇怪的是,导航到另一个Fragment时状态已正确保存。 The error only occurs when I change the orientation. 仅当我更改方向时才会发生错误。

Edit: On request here's the Profile class 编辑:根据要求,这里是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;
}

} }

Gson object Gson对象

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

Exclusion Class 排除类

private class ParseExclusion implements ExclusionStrategy {

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

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

}

Finally: 最后:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM