Как сериализовать нулевое значение при использовании интерфейса Parcelable - PullRequest
60 голосов
/ 06 мая 2011

относительно моего примера кода, что мне делать, если переменные одного из Locable имеют значение null?Например, теперь, если l.getZoom () возвращает null, я получил NullPointerException.

@Override
public void writeToParcel(Parcel parcel, int arg1) {
    parcel.writeInt(count);
    for(Locable l:locableArr){
        parcel.writeInt(l.getOriginId());
        parcel.writeInt(l.getLocableType());
        parcel.writeInt(l.getZoom());
        parcel.writeDouble(l.getLatituda());
        parcel.writeDouble(l.getLongituda());
        parcel.writeString(l.getTitle());
        parcel.writeString(l.getSnipet());
    }

}

Спасибо!

Ответы [ 4 ]

102 голосов
/ 27 мая 2012

Вы можете использовать Parcel.writeValue для сортировки универсального объекта с нулевым значением.

18 голосов
/ 02 мая 2015

Я использую класс Parcelable, который также имеет поля Integer и Boolean, и эти поля могут быть нулевыми.

У меня были проблемы с использованием универсального метода Parcel.writeValue, особенно когда я пытался прочитать его обратно через Parcel.readValue. Я продолжал получать исключение времени выполнения, в котором говорилось, что он не может определить тип выделенного объекта.

В конечном итоге мне удалось решить эту проблему, используя Parcel.writeSerializable и Parcel.readSerializable с приведением типа, поскольку и Integer, и Boolean реализуют интерфейс Serializable. Методы чтения и записи обрабатывают для вас значения null.

14 голосов
/ 21 декабря 2012

Это решение, которое я придумал для безопасного написания строк:

private void writeStringToParcel(Parcel p, String s) {
    p.writeByte((byte)(s != null ? 1 : 0));
    p.writeString(s);
}

private String readStringFromParcel(Parcel p) {
    boolean isPresent = p.readByte() == 1;
    return isPresent ? p.readString() : null;
}
13 голосов
/ 24 мая 2012

В большинстве кодов сериализации, которые я видел, используются либо флаги, чтобы указать наличие / отсутствие значения, ИЛИ предшествует значению поле счетчика (например, при записи массивов), где поле счетчика просто устанавливается в ноль, еслизначение вообще не существует.

Изучение исходного кода основных классов Android показывает код, подобный этому (из класса Message):

    if (obj != null) {
        try {
            Parcelable p = (Parcelable)obj;
            dest.writeInt(1);
            dest.writeParcelable(p, flags);
        } catch (ClassCastException e) {
            throw new RuntimeException(
                "Can't marshal non-Parcelable objects across processes.");
        }
    } else {
        dest.writeInt(0);
    }

или этот (из класса Intent):

    if (mCategories != null) {
        out.writeInt(mCategories.size());
        for (String category : mCategories) {
            out.writeString(category);
        }
    } else {
        out.writeInt(0);
    }

Мое предложение: Если в вашем коде нет функциональной разницы между "zoom == null" и "zoom == 0", то я бы просто объявил zoom какпримитив (int вместо Integer) ИЛИ инициализируйте его в ноль в конструкторе и убедитесь, что вы никогда не установите его в ноль (тогда вы можете быть уверены, что он никогда не будет нулевым, и вам не придется добавлять специальный кодчтобы справиться с этим в ваших методах сериализации / десериализации).

...