Возможность сериализации объектов предоставляется напрямую инфраструктурой языка Java. Однако Android также предоставляет интерфейс Parcelable, который по сути также позволяет сериализовать объекты, как и Serializable, но является более оптимизированным для Android. И подобные объекты Parcelable также можно передавать между двумя activity или использовать каким-то иным образом.
Например, в прошлой теме данные передавались между activity в виде объектов User, которые использовали сериализацию. Теперь пусть класс User применяет интерфейс Parcelable:
package com.example.viewapp; import android.os.Parcel; import android.os.Parcelable; public class User implements Parcelable { private String name; private String company; private int age; public static final Creator<User> CREATOR = new Creator<User>() { @Override public User createFromParcel(Parcel source) { String name = source.readString(); String company = source.readString(); int age = source.readInt(); return new User(name, company, age); } @Override public User[] newArray(int size) { return new User[size]; } }; public User(String name, String company, int age){ this.name = name; this.company = company; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getCompany() { return company; } public void setCompany(String company) { this.company = company; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(name); dest.writeString(company); dest.writeInt(age); } }
Интерфейс android.os.Parcelable предполагает реализацию двух методов: describeContents()
и writeToParcel()
.
Первый метод описывает контент и возвращает некторое числовое значение. Второй метод пишет в объект Parcel содержимое объекта User.
Для записи данных объекта в Parcel используется ряд методов, каждый из которых предназначен для определенного типа данных. Основные методы:
writeString()
writeInt()
writeFloat()
writeDouble()
writeByte()
writeLong()
writeIntArray()
writeValue() (записывает объект типа Object)
writeParcelable() (записывает объект типа Parcelable)
Кроме того, объект Parcelable должен содержать статическое поле CREATOR, которое представляет объект Creator<User>
.
Причем этот объект реализует два метода. Они нужны для создания их ранее сериализованных данных исходных объектов типа User.
Так, метод newArray()
создает массив объект User.
Метод createFromParcel создает из Parcel новый объект типа User. То есть этот метод противоположен по действию методу writeToParcel.
Для получения данных из Parcel применяются методы типа readString()
, readInt()
, readParcelable()
и так далее - для чтения определенных типов данных.
Причем важно, что данные в createFromParcel считываются из объекта Parcel именно в том порядке, в котором они добавляются в этот объект в методе writeToParcel.
Допустим в activity, которая называется SecondActivity мы будем получать объект User:
package com.example.viewapp; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.widget.TextView; public class SecondActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TextView textView = new TextView(this); textView.setTextSize(26); textView.setPadding(16, 16, 16, 16); Bundle arguments = getIntent().getExtras(); User user; if(arguments!=null){ user = arguments.getParcelable(User.class.getSimpleName()); textView.setText("Name: " + user.getName() + "\nCompany: " + user.getCompany() + "\nAge: " + String.valueOf(user.getAge())); } setContentView(textView); } }
Для получения объекта Parcelable, переданного в activity, применяется метод getParcelable()
. Причем никакого приведения типов не требуется.
Для тестирования передачи Parcelable определим в файле activity_main.xml простейший интерфейс для MainActivity:
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/nameLabel" android:layout_width="0dp" android:layout_height="20dp" android:text="Name:" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent"/> <EditText android:id="@+id/name" android:layout_width="0dp" android:layout_height="40dp" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toBottomOf="@+id/nameLabel"/> <TextView android:id="@+id/companyLabel" android:layout_width="0dp" android:layout_height="20dp" android:text="Company:" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toBottomOf="@+id/name"/> <EditText android:id="@+id/company" android:layout_width="0dp" android:layout_height="40dp" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toBottomOf="@+id/companyLabel" /> <TextView android:id="@+id/ageLabel" android:layout_width="0dp" android:layout_height="20dp" android:text="Age:" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toBottomOf="@+id/company"/> <EditText android:id="@+id/age" android:layout_width="0dp" android:layout_height="40dp" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toBottomOf="@+id/ageLabel"/> <Button android:id="@+id/btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="onClick" android:text="Save" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toBottomOf="@+id/age"/> </androidx.constraintlayout.widget.ConstraintLayout>
А в коде MainActivity определим передачу данных в SecondActivity:
package com.example.viewapp; import androidx.appcompat.app.AppCompatActivity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.EditText; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void onClick(View v) { EditText nameText = findViewById(R.id.name); EditText companyText = findViewById(R.id.company); EditText ageText = findViewById(R.id.age); String name = nameText.getText().toString(); String company = companyText.getText().toString(); int age = Integer.parseInt(ageText.getText().toString()); User user = new User(name, company, age); Intent intent = new Intent(this, SecondActivity.class); intent.putExtra(User.class.getSimpleName(), user); startActivity(intent); } }