Подтвердить что ты не робот

Как сериализовать нулевое значение при использовании интерфейса Parcelable

в отношении моего примера кода вниз, что мне делать, если одна переменная 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());
    }

}

Спасибо!

4b9b3361

Ответ 1

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

Ответ 2

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

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

    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", тогда я бы просто объявил масштаб как примитив (int вместо Integer) ИЛИ инициализируйте его в ноль в конструкторе и убедитесь, что вы никогда не устанавливали его в null (тогда вы можете быть уверены, что он никогда не будет пустым, и вам не придется добавлять специальный код для работы с этим в ваших методах сериализации/десериализации).

Ответ 3

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

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

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

Ответ 4

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

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