реализация Parcelable в производном графическом классе для onSaveInstanceState(Bundle)

Я хочу сохранить и восстановить некоторые данные для изменения ориентации экрана (книжная/альбомная).

Для этого я реализовал onSaveInstanceState и onRestoreInstanceState в своем классе, который содержит список, который я хочу восстановить. Вроде работает, и в классе MyObject я реализовал Parcelable.

Проблема в том, что мой объект расширяет GifImageButton и реализует Parcelable, поэтому я получаю эту ошибку в своих конструкторах объектов: "Для pl.droidsonroids нет конструктора по умолчанию. gif.GifImageButton"

public class MyDerivedClass extends MyBaseClass { // extends AppCompatActivity
    ArrayList<MyObject> list;

        @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.episode_five);
    if(savedInstanceState == null || !savedInstanceState.containsKey("key"))     {
            String[] colors = {"black", "red"};
            String[] numbers = {"one", "two"};

            list = new ArrayList<MyObject>();
            for(int i = 0; i < numbers.length; i++)
                list.add(new MyObject(numbers[i], colors[i]));
        }
        else {
            list = savedInstanceState.getParcelableArrayList("key");
        }
    }

    @Override
     protected void onSaveInstanceState(Bundle outState) {
        outState.putParcelableArrayList("key", list);
        super.onSaveInstanceState(outState);
    }
    @Override
    protected void onRestoreInstanceState(Bundle inState) {
        list = inState.getParcelableArrayList("key");
        super.onSaveInstanceState(inState);
        init();
    }
    public void init() {
        list.add(new MyObject("three", "transparent"));
        list.add(new MyObject("for", "white"));
    }
}

и для решения проблемы просмотрите приведенный ниже код:

Я хочу расширить GifImageButton, но потом получаю сообщение об ошибке "Нет доступного конструктора по умолчанию для pl.droidsonroids.gif.GifImageButton" по адресу:

public MyObject(номер строки, цвет строки) AND public MyObject(Parcel in)

Примечание: если я удалю: «extends GifImageButton» и «public MyObject (Context context, AttributeSet attrs)», тогда код будет скомпилирован.

class MyObject extends GifImageButton implements Parcelable {
    String color;
    String number;

    public MyObject(Context context, AttributeSet attrs) {
        super(context, attrs);
        setImageResource(R.drawable.a);
    }

    public MyObject(String number, String color) {
        this.color = color;
        this.number = number;
    }

    private MyObject(Parcel in) {
        color = in.readString();
        number = in.readString();
    }

    public int describeContents() {
        return 0;
    }

    @Override
    public String toString() {
        return number + ": " + color;
    }

    public void writeToParcel(Parcel out, int flags) {
        out.writeString(color);
        out.writeString(number);
    }

public static final Parcelable.Creator<MyObject> CREATOR = new     Parcelable.Creator<MyObject>() {
        public MyObject createFromParcel(Parcel in) {
            return new MyObject(in);
        }

        public MyObject[] newArray(int size) {
            return new MyObject[size];
        }
    };
}

Могу ли я расширить GifImageButton в своем классе объектов, который реализует Parcelable? если нет, то как я могу это исправить?


person Maor Cohen    schedule 24.11.2016    source источник


Ответы (2)


Сообщение об ошибке появляется, потому что вам нужно вызвать конструктор суперкласса в вашем конструкторе. Если явного вызова нет, компилятор вставляет вызов конструктора без аргументов. Однако все конструкторы суперкласса имеют некоторые аргументы, поэтому компиляция завершается неудачно.

В вашем случае я бы вообще не реализовал Parcelable в вашем классе. Суперкласс не реализует его, поэтому вам также нужно будет каким-то образом сохранить состояние суперкласса, что будет невозможно сделать. Суперкласс — это View, поэтому он сохраняет ссылку на текущую активность, которую нельзя поместить в Parcel.

Вместо этого вы должны сохранить не сам экземпляр, а нужное вам состояние. Ваше состояние в настоящее время выражается двумя строками. Вы можете создать отдельный класс State внутри MyObject:

static class State implements Parcelable {
    private String color;
    private String number;

    //Parcelable implementation omitted
}

Затем вы реализуете для него Parcelable. MyObject будет иметь поле private State state вместо текущих двух полей, конструктор, который принимает State, и метод State getState(), который будет возвращать состояние. Когда вам нужно сохранить состояние, вы не сохраняете объект, вы получаете его состояние и сохраняете его. Когда вам нужно восстановить, вы сначала восстанавливаете State, а затем используете его с конструктором для создания нового MyObject с тем же состоянием, что и раньше.

person Malcolm    schedule 24.11.2016
comment
Я попробовал это, но затем в MyDerivedClass у меня есть ошибки. например, в onCreate в строке: list = saveInstanceState.getParcelableArrayList(key); Ошибка: предполагаемый тип MyObject для параметра типа «T» не находится в пределах его границ; должен реализовать «android.os.Parcelable». другая ошибка в onSaveInstanceState в строке: outState.putParcelableArrayList(key, list); ошибка: Неверный тип второго аргумента; Найден 'MyObject', требуется: 'java.util.ArrayList'? расширяет android.os.Parcelable›' - person Maor Cohen; 24.11.2016
comment
@ErezShmiel Как я уже сказал, вам нужно сохранять состояния, а не сами объекты. Конечно, если у вас есть список объектов и вы пытаетесь его сохранить, вы не сможете этого сделать, потому что он не реализует Parcelable. Вам нужно получить состояния всех объектов в списке, создать новый ArrayList и вместо этого поместить его в Bundle. - person Malcolm; 24.11.2016

ваш класс MyObject имеет частный конструктор MyObject (Parcel in), сделайте его общедоступным, чтобы компилятор мог получить к нему доступ

person Alex Shutov    schedule 24.11.2016