Статьи

Передача данных между операциями с Android Parcelable

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, поскольку вы неявно указываете, как сохранять и извлекать ваши данные.

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