Android-приложение обычно состоит из нескольких действий, которые должны передавать данные между собой. Например, основной вид деятельности со списком элементов и соответствующий дополнительный вид деятельности, чтобы показать детали этих элементов. Для перехода от одного занятия к другому вы используете класс intent
чтобы соединить их вместе. Это позволяет запустить действие и при необходимости вернуться позже (если вы новичок в намерениях, в документах разработчика Google есть хороший ресурс , объясняющий процесс)
Частью процесса является отправка данных между действиями, и вы делаете это с помощью методов putExtra
и getExtra
нашего объекта intent
. Идея состоит в том, чтобы сделать процесс передачи различных типов данных простым:
//Inside first activity Intent intent = new Intent(MainActivity.this, DetailActivity.class); intent.putExtra("name", "John Smith"); intent.putExtra("age", 26); //inside second activity Intent intent = getIntent(); String suburb = intent.getStringExtra("name"); Integer age = intent.getIntExtra("age");
Это хорошо работает для базовых типов данных, таких как string
, bool
и Integer
но не работает для объектов. Что делать, если вы хотите передать объект и его данные из одного действия в другое? Вы используете интерфейс parcelable
Представляем интерфейс Parcelable
Поскольку объекты могут содержать любое количество смешанных типов данных, вы не можете использовать putExtra
для перемещения значений. В Java некоторое время можно было serialize
объекты, но это медленный процесс, поскольку система должна выполнять тяжелую работу для перемещения данных. Parcelable — это интерфейс только для Android, используемый для сериализации класса, поэтому его свойства могут быть переданы из одного действия в другое.
Реализация Parcelable
Интерфейс Parcelable добавляет методы ко всем классам, которые вы хотите передавать между действиями. Эти методы — то, как parcelable деконструирует объект в одном действии и реконструирует его в другом.
В этом примере вы узнаете, как реализовать parcelable в простом классе. Я использовал этот класс в одной из моих предыдущих статей, где я создал список свойств и соответствующее действие подробно. Идея состоит в том, что когда вы выбираете свойство в виде списка, вы переходите в расширенный подробный вид, чтобы узнать больше информации.
Создание класса свойства
Сначала создайте класс для хранения информации о каждом свойстве. Начните с добавления следующего в новый файл класса в вашем проекте.
public class Property implements { //property basics private int streetNumber; private String streetName; private String suburb; private String state; private String description; private String image; private Double price; private int bedrooms; private int bathrooms; private int carspots; private Boolean featured; //main constructor public Property(int streetNumber, String streetName, String suburb, String state, String description, Double price, String image, int bedrooms, int bathrooms, int carspots, Boolean featured){ this.streetNumber = streetNumber; this.streetName = streetName; this.suburb = suburb; this.state = state; this.description = description; this.price = price; this.image = image; this.bedrooms = bedrooms; this.bathrooms = bathrooms; this.carspots = carspots; this.featured = featured; } //getters public int getStreetNumber() { return streetNumber; } public String getStreetName() {return streetName; } public String getSuburb() {return suburb; } public String getState() {return state; } public String getDescription() {return description; } public Double getPrice() {return price; } public String getImage() { return image; } public int getBedrooms(){ return bedrooms; } public int getBathrooms(){ return bathrooms; } public int getCarspots(){ return carspots; } public Boolean getFeatured(){return featured; } }
Класс содержит ряд свойств, функции-получатели и конструктор для создания единого объекта класса.
Добавьте интерфейс Parcelable
Вот основная часть, реализующая интерфейс. Измените объявление класса следующим образом:
public class Property implements Parcelable { ... }
Добавьте следующие методы внутри класса. Я скоро расскажу, как они работают.
//write object values to parcel for storage public void writeToParcel(Parcel dest, int flags){ //write all properties to the parcle } //constructor used for parcel public Property(Parcel parcel){ //read and set saved values from parcel } //creator - used when un-parceling our parcle (creating the object) public static final Parcelable.Creator<Property> CREATOR = new Parcelable.Creator<Property>(){ @Override public Property createFromParcel(Parcel parcel) { return new Property(parcel); } @Override public Property[] newArray(int size) { return new Property[0]; } }; //return hashcode of object public int describeContents() { return hashCode(); }
Parcelable нужен этот код для работы. Он обрабатывает процесс копирования данных вашего объекта в parcel
для передачи между действиями, а затем воссоздает объект на другой стороне.
Давайте разберемся, как это все работает.
Способ написания — writeToParcel
В этом методе вы добавляете все свои свойства класса в посылку при подготовке к передаче. Вы используете каждый из методов write
чтобы добавить каждое из ваших свойств.
//write object values to parcel for storage public void writeToParcel(Parcel dest, int flags){ dest.writeString(streetName); dest.writeString(suburb); dest.writeString(state); dest.writeString(description); dest.writeString(image); dest.writeInt(streetNumber); dest.writeValue(featured); dest.writeDouble(price); dest.writeInt(bedrooms); dest.writeInt(bathrooms); dest.writeInt(carspots); }
Примечания :
- Порядок, в котором вы пишете эти значения, важен. Когда вы собираете эти значения позже, вам нужно будет собрать их в том же порядке .
- Если вы собираетесь отправлять
boolean
значения (например, свойствоfeatured
). Вам придется использоватьwriteValue
а затем принудительно привести его кboolean
writeValue
на другой стороне, так как нет никакого собственного метода добавления логических значений.
Метод чтения — Property
Этот метод является конструктором, вызываемым в операции получения, где вы будете собирать значения.
Когда вторичное действие вызывает метод getParcelableExtra
объекта intent
чтобы запустить процесс. В этом конструкторе вы собираете значения и настраиваете свойства объекта:
//constructor used for parcel public Property(Parcel parcel){ streetName = parcel.readString(); suburb = parcel.readString(); state = parcel.readString(); description = parcel.readString(); image = parcel.readString(); streetNumber = parcel.readInt(); featured = (Boolean) parcel.readValue(null); price = parcel.readDouble(); bedrooms = parcel.readInt(); bathrooms = parcel.readInt(); carspots = parcel.readInt(); }
На данный момент вы заполнили объект данными.
Если вы используете свой собственный объект, тогда имя этой функции будет соответствовать имени вашего собственного класса, например, person
, animal
, place
, имя должно соответствовать имени класса.
Метод Создателя
Parcelable требует, чтобы этот метод связывал все вместе. Здесь мало что нужно сделать, так как метод createFromParcel
вернет ваш вновь заполненный объект.
//used when un-parceling our parcel (creating the object) public static final Parcelable.Creator<Property> CREATOR = new Parcelable.Creator<Property>(){ @Override public Property createFromParcel(Parcel parcel) { return new Property(parcel); } @Override public Property[] newArray(int size) { return new Property[0]; } };
Другие методы — describeContents
Этот метод не делает много.
//return hashcode of object public int describeContents() { return hashCode(); }
Начало намерения в первом упражнении
Внутри первого упражнения создайте объект intent
и используйте метод putExtra
для добавления всего класса в качестве дополнительного. Это будет работать, только если вы правильно реализовали интерфейс Parcelable
(поскольку в этот момент parcelable начинает сериализацию вашего объекта).
Intent intent = new Intent(MainActivity.this, DetailActivity.class); intent.putExtra("Property", property); startActivity(intent);
Если это сработает, откроется новое действие. Вам нужно будет убедиться, что действие добавлено в ваш файл манифеста.
Сбор ценностей во вторичной деятельности
Теперь, когда вы во втором упражнении, вам нужно собрать объект intent
и извлечь класс property
который был преобразован в parcel
. Сделав это, вы можете вызвать стандартные методы, чтобы получить такие данные, как имя свойства, цена и описание.
//collect our intent Intent intent = getIntent(); Property property = intent.getParcelableExtra("Property"); //now collect all property values String streetName = property.getStreetName(); Integer streetNumber = property.getStreetNumber(); String suburb = property.getSuburb(); String state = property.getState(); String description = property.getDescription(); Double price = property.getPrice(); Integer bedrooms = property.getBedrooms(); Integer bathrooms = property.getBathrooms(); Integer carspots = property.getCarspots(); String image = property.getImage(); Integer imageID = this.getResources().getIdentifier(image, "drawable", this.getPackageName()); String address = streetNumber + " " + streetName + ", " + suburb + ", " + state;
Передать посылку
Как вы видите, есть работа по настройке и запуску пакета, но как только все это заработает, отдача того стоит.
Вы можете перемещать целые объекты из одного занятия в другое, сохраняя все методы и способности класса. Это замечательно, если у вас есть сложный метод, который преобразует ваши данные.
Вам больше не нужно запоминать разные имена, которые вы обычно передаете объекту intent
качестве дополнительных данных, например, String streetName = intent.getStringExtra("streetName");
, Вы можете получить свой объект и двигаться дальше.
Процесс быстрый и оптимизированный. Делать это таким образом быстрее, чем использовать функцию serialize
Java, поскольку вы неявно указываете, как сохранять и извлекать ваши данные.
Пожалуйста, дайте мне знать, если у вас есть какие-либо комментарии или вопросы .