序列化 android.net.Uri 对象

10

我想对类型为android.net.Uri的对象进行序列化。

下面是我的模型类,带有writeObject和readObject方法。

public class ReminderObject implements Serializable {
private boolean isReminderOn;
private int fromHours, toHours;
private int interval;
private ArrayList<CharSequence> daysToRepeat;
private Uri toneToPlay;
private AdvanceSettingsObject adv;

public ReminderObject(boolean isReminderOn, int fromHours, int toHours,
        int interval, ArrayList<CharSequence> daysToRepeat, Uri toneToPlay,
        AdvanceSettingsObject adv) {
    super();
    this.isReminderOn = isReminderOn;
    this.fromHours = fromHours;
    this.toHours = toHours;
    this.interval = interval;
    this.daysToRepeat = daysToRepeat;
    this.toneToPlay = toneToPlay;
    this.adv = adv;
} 
/*
getters and setters
*/
    public void writeObject(ObjectOutputStream op){
    try {
        op.defaultWriteObject();
        op.writeChars(toneToPlay.toString());
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
public void readObject(ObjectInputStream in){
    try{
        in.defaultReadObject();
        toneToPlay = Uri.parse(in.readUTF());
    }catch(Exception e){

    }
}

}

MainActivity的代码片段:

try {
        ObjectOutputStream os = new ObjectOutputStream(new     FileOutputStream(Environment.getExternalStorageDirectory().getAbsolutePath()+"/ReminderData.txt")    );
        os.writeObject(reminder); // Getting above mentioned Exception here
        Log.i("TAG","reminder serialized");
        ObjectInputStream is = new ObjectInputStream(new FileInputStream(Environment.getExternalStorageDirectory().getAbsolutePath()+"/ReminderData.txt"));
        ReminderObject reminderRead = (ReminderObject) is.readObject();
        if(reminderRead!=null)
            Log.i("TAG", "Deserialized Reminder object is : "+reminderRead.toString());
        else{
            Log.i("TAG", "Null received");
        }
    } catch(ClassNotFoundException cnf){
        cnf.printStackTrace();
    } catch (FileNotFoundException e) {     
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

遇到的异常:

03-31 23:47:59.246: W/System.err(12681): java.io.NotSerializableException: android.net.Uri$HierarchicalUri 03-31 23:47:59.246: W/System.err(12681): at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1364) 03-31 23:47:59.246: W/System.err(12681): at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1671) 03-31 23:47:59.246: W/System.err(12681): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1517) 03-31 23:47:59.246: W/System.err(12681): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1481) 03-31 23:47:59.246: W/System.err(12681): at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:979) 03-31 23:47:59.246: W/System.err(12681): at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:368) 03-31 23:47:59.246: W/System.err(12681): at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1074) 03-31 23:47:59.246: W/System.err(12681): at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1404) 03-31 23:47:59.246: W/System.err(12681): at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1671) 03-31 23:47:59.246: W/System.err(12681): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1517) 03-31 23:47:59.246: W/System.err(12681): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1481) 03-31 23:47:59.246: W/System.err(12681): at com.navkar.navkarreminder.SetReminderActivity.scheduleReminder(SetReminderActivity.java:595)

请求帮助。

4个回答

10

URI private Uri toneToPlay 不可序列化。因此,有一种替代方法,可以将数据类型 URI 更改为 String,并在使用时将您的 URI 转换为字符串和字符串转换为 URI。

URI 转字符串

Uri uri;
String stringUri;
stringUri = uri.toString();

字符串转换为Uri

Uri uri;
String stringUri;
uri = Uri.parse(stringUri);

8

我认为问题在于您保存的数据成员 problem

private Uri toneToPlay 是一种不可序列化的数据类型,因此您无法对其进行序列化。


3
是的,Uri不可序列化,因此我将其更改为字符串。 - shahharshil46
不要忘记标记答案为已解决。这有助于其他人找到答案。 - User10001
1
Uri 可以序列化! 点击此链接查看 https://dev59.com/4WEh5IYBdhLWcg3wVCLK - NecipAllef

2
考虑使用java.net.URI类代替。它几乎具有相同的功能,但是它是Serializable的。您可以轻松地从Uri转换为URI(反之亦然):
Uri转URI: new URI(uri.toString()) URI转Uri: Uri.parse(uri.toString())

2

当我们想要保留Uri作为成员变量(例如为了方便),并且需要序列化类时,可能的解决方案之一是使Uri transient 并序列化Uri字符串(就像@King of Masses展示的那样)。

这样,我们不会改变POJO的公共接口,并且不会序列化Uri,从而以一种懒惰的方式创建它。

带有Uri的可序列化POJO可以如下所示:

class MediaFile implements Serializable {

    private static final long serialVersionUID = -420L;    

    @Nullable
    private transient Uri mFileUri;

    @NonNull
    private String mFileUriString;

    MediaFile(@NonNull Uri fileUri) {
        this.mFileUriString = fileUri.toString();
    }

    @NonNull
    public getFileUri() {
        if (mFileUri == null) {
            mFileUri = Uri.parse(mFileUriString);
        }
        return mFileUri;
    }


}

For kotlin:

class MediaFile(uri: Uri) : Serializable {
    private val mUriString = uri.toString();
    @Transient private val mUri by lazy { Uri.parse(mUriString) }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接