Для протокола Parcelable требуется объект Parcelable.Creator, называемый CREATOR (у меня есть CREATOR)

Я пытаюсь передать Parcelable данные от одного намерения к другому, и это ошибка, которую я получаю:

08-31 14:12:22.709: E/AndroidRuntime(9931): FATAL EXCEPTION: main
08-31 14:12:22.709: E/AndroidRuntime(9931): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.matejsoftware.cardscoretracker/com.matejsoftware.cardscoretracker.Igra}: android.os.BadParcelableException: Parcelable protocol requires a Parcelable.Creator object called  CREATOR on class com.matejsoftware.cardscoretracker.Novaigra$Player

Дело в том, что у меня есть объект Parcelable.Creator. Я отправлю весь код Parcelable ниже:

public class Player implements Parcelable{
    String name;
    int score;
    @Override
    public int describeContents() {
        // TODO Auto-generated method stub
        return 0;
    }
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
        dest.writeInt(score);
    }

    public Player(Parcel source){
        score = source.readInt();
        name = source.readString();
    }

    public Player(int score, String name){
        this.score = score;
        this.name = name;
    }
}

public class MyCreator implements Parcelable.Creator<Player> {

    @Override
    public Player createFromParcel(Parcel source) {
        return new Player(source);
    }

    @Override
    public Player[] newArray(int size) {
        return new Player[size];
    }

}

Что-то не так с CREATOR? Приложение аварийно завершает работу, как только я нажимаю кнопку, чтобы начать следующую операцию.

Вот как я "извлекаю" Parcelable данные во втором действии:

//global variable
ArrayList<Player> playersParceledData;

//This is in onCreate
playersData = getIntent();
playersParceledData = playersData.getParcelableArrayListExtra("parceledData");

Кроме того, так я помещаю объекты класса в ParcelableArrayListExtra:

Player newPlayer = new Player(0, text);
playersParceledData.add(newPlayer);
zacniIgro.putParcelableArrayListExtra("parceledData", playersParceledData);

Ответы

Ответ 1

У вас другая последовательность при чтении из Parcel, чем та, в которой вы пишете.

В writeToParcel() вы сначала помещаете String, но в HeatFriendDetail(Parcel in) вы сначала читаете целое число. Это не правильный путь, потому что порядок или чтение/запись имеют значение.

Ниже приведен код, который устанавливает правильный порядок при записи/чтении данных в/из Parcel (также см. Эту ссылку):

public class FriendDetail implements Parcelable {

    private String full_name;
    private int privacy;

    public HeatFriendDetail(Parcel in) {
        this.full_name = in.readString();
        this.privacy = in.readInt();
    }

    public HeatFriendDetail() {

    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {

        dest.writeString(this.full_name);
        dest.writeInt(this.privacy);
    }

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

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

    // GETTER SETTER//
}

Ответ 2

Я получил эту ошибку только в выпуске apk, потому что CREATOR не был общедоступным.

Я изменил это:

static final Parcelable.Creator<Station> CREATOR = new Parcelable.Creator<Station>() {

Для этого:

public static final Parcelable.Creator<Station> CREATOR = new Parcelable.Creator<Station>() {

Ответ 3

Просто наткнулся на это.

У меня была догадка, и я посмотрел в файл сопоставления ProGuard.

Обычно я объявляю CREATOR следующим образом:

    public static final Parcelable.Creator<ClassA> CREATOR = 
            new Parcelable.Creator<ClassA>() {

который отображается в файле сопоставления следующим образом:

    android.os.Parcelable$Creator CREATOR -> CREATOR

.. за исключением одного класса, класса, о котором сообщалось с ошибкой. Я объявил следующее:

    public static Creator<ClassB> CREATOR =
            new Creator<ClassB>() {

Ло и вот:

    android.os.Parcelable$Creator CREATOR -> a

Итак, если вы получаете это исключение в своей производственной версии, проверьте свой файл сопоставления. Я думаю, ProGuard действительно чувствителен к тому, как объявляется CREATOR при принятии решения не обфускации его.

Ответ 4

У меня возникло это сообщение об ошибке, когда класс CREATOR не был статическим

Ответ 5

Если вы используете правила proguard, добавьте эту строку в ваш proguard-rules.pro

-keepnames class * implements android.os.Parcelable {
public static final ** CREATOR;

}

Ответ 6

Попробуйте этот способ

// create List of player
        ArrayList<HashMap<String, String>> players = new ArrayList<HashMap<String, String>>();

        //create Player

        HashMap<String, String> player = new HashMap<String, String>();
        player.put("score", "20");//replace 20 with your score variable
        player.put("name", "Biraj");//replace Biraj with your name variable

        // Add to arraylist

        players.add(player);

        // pass to intent

        Intent i;
        i.putExtra("PLAYERS", players);

        // read From intent

        ArrayList<HashMap<String, String>> playerFromintent = (ArrayList<HashMap<String, String>>) getIntent().getSerializableExtra("PLAYERS");

        // read from ArrayList

        for (HashMap<String, String> hashMap : playerFromintent) {
            System.out.println("Name : " + hashMap.get("name"));
            System.out.println("Score : " + hashMap.get("score"));
        }