У меня есть массив, содержащий сериализуемые объекты, и я пытаюсь использовать putExtra () от Intent и getSerializable () из Bundle. Однако я получаю исключение приведения класса и не понимаю, почему.

Ниже приведен код. UserInfo - это мой собственный класс, который реализует Serializable, и я смог передавать отдельные объекты UserInfo между действиями. Я столкнулся с этой проблемой только при попытке использовать массив.

Код, отправляющий сериализуемый:

Intent intent = new Intent( JOIN_GROUP ); //JOIN_GROUP is a constant string

String user_ids[] = packet.userIDs();

int length = user_ids.length;
UserInfo users[] = new UserInfo[length];

for ( int i = 0; i < length; ++i )
    users[i] = getUserByID( user_ids[i] );

intent.putExtra( USERS_IN_GROUP, users );

Код, извлекающий сериализуемый:

Bundle extra = intent.getExtras();          
String action = intent.getAction();

if ( action.equals(IMService.JOIN_GROUP) )
{   
    //CLASS CAST EXCEPTION
    UserInfo users[] = (UserInfo[]) extra.getSerializable( IMService.USERS_IN_GROUP ); 
}

Вот ошибка:

enter image description here

Вопрос

Я знаю, что, вероятно, мог бы просто использовать другую структуру данных, но я хотел бы понять, почему массив не работает, поскольку массивы сериализуемы?

РЕДАКТИРОВАТЬ: SnyersK смог получить более простой, но похожий сценарий работы. Я попробовал то же самое, но все равно получаю то же исключение. Он превратил мой массив тестов в объект при извлечении массива, что привело к исключению приведения.

Мой тестовый объект:

package types;

import java.io.Serializable;

public class Test implements Serializable {

    private static final long serialVersionUID = 1L;

    private String hello = "hello";

}

Код для передачи массива тестовых объектов:

Test myArray[] = new Test[] { new Test(), new Test() };
Intent i = new Intent( this, Login.class );
i.putExtra( "key", myArray );

Код для получения массива тестовых объектов:

Bundle extras = getIntent().getExtras();
Test array[] = (Test[]) extras.getSerializable( "key" ); //Class Cast Exception
5
Kacy 25 Фев 2015 в 16:19

4 ответа

Лучший ответ

Видимо это ошибка в старых версиях Android. (Версия 5.0.1 - единственная протестированная версия, на которой она работает, как ожидалось, возможно, она работает с 5.0 и выше)

Ошибка

Допустим, у нас есть массив объекта с именем User, который реализует Serializable.

User[] users;

Когда мы пытаемся передать этот массив другому действию с помощью такого намерения

intent.putExtra("myKey", users);

Наш users будет преобразован в Object[].

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

User[] users = getIntent().getSerializableExtra("myKey");

Мы получим исключение ClassCastException.

Из документации мы можем сделать вывод, что это не должно быть проблемой, поскольку Array является сериализуемым классом, а putExtra(String key, Serializable value) был добавлен после api 1.

Если вы хотите передать Array через намерение в версиях Android до Android 5.0.1 (возможно, некоторые старые версии также работают, но до Android 4.3 это НЕ работает) Вам придется обойти это. Вы можете сделать это, преобразовав свой Array в ArrayList.

ИЗМЕНИТЬ

Другой обходной путь - это копирование вашего дополнения в новый массив, поэтому вам не нужно его приводить. Однако я не уверен в положительных / отрицательных последствиях этого метода. Это выглядело бы так:

Object[] array = (Object[]) getIntent().getSerializableExtra("key");
User[] parsedArray = Arrays.copyOf(array, array.length, User[].class);

Я нашел этот метод здесь: Как преобразовать массив объектов в строковый массив в Java.

12
SnyersK 1 Мар 2018 в 12:44

Это внутренний класс UserInfo или отдельный файл класса Java?

Если это внутренний класс, то родительский класс также должен быть сериализуемым.

Если нет, сделайте UserInfo класс реализацией Parcelable и используйте

intent.putParcelableArrayListExtra(USERS_IN_GROUP, new ArrayList<UserInfo>(Arrays.asList(users)));
0
Vamsi 25 Фев 2015 в 14:00

Попробуйте вот так:

Intent intent = new Intent( JOIN_GROUP ); //JOIN_GROUP is a constant string

String user_ids[] = packet.userIDs();

int length = user_ids.length;
UserInfo users[] = new UserInfo[length];

for ( int i = 0; i < length; ++i )
    users[i] = getUserByID( user_ids[i] );

Bundle bnd=new Bundle();
bnd.putSerializable(USERS_IN_GROUP, users);

При отправке вы присоединяетесь к намерению, а во время ретрвнга вы читаете из пакета (что является дополнительным намерением).

0
No Name 25 Фев 2015 в 13:24

Заменить

intent.putExtra( USERS_IN_GROUP, users );

С участием

intent.putExtra( USERS_IN_GROUP, new ArrayList<UserInfo>(Arrays.asList(users)));
2
Y.S 25 Фев 2015 в 13:49