Intent Explicit dengan Parcelable
Bagi yang belum mengenal apa itu Data Classes, berikut penjelasan singkatnya. Data Classes adalah sebuah kelas biasa yang tidak bergantung pada kelas lainnya.
Class ini berfungsi untuk menyimpan model data suatu obyek. Class ini sama seperti POJO (Plain Old Java Object) pada Java yang memiliki properti/variabel dan metode setter-getter.
Namun di Kotlin semua itu sudah tergenerate otomatis dan tidak terlihat, sehingga kode menjadi lebih ringkas. Sebagai contoh kelas Kotlin dan Java di bawah ini memiliki fungsi yang sama:
- data class MyBean(val someProperty: String)
- public class MyBean {
- private String someProperty;
- public MyBean(){
- }
- public String getSomeProperty() {
- return someProperty;
- }
- public void setSomeProperty(String someProperty) {
- this.someProperty = someProperty;
- }
- }
Lalu apa kegunaan Data Classes? Data classes akan membantu kita saat aplikasi semakin kompleks. Contohnya, data classes bisa kita gunakan untuk melakukan koneksi ke server untuk request API atau akses ke database lokal dengan SQLite. Untuk lebih lengkapnya Anda bisa membaca lebih lanjut tentang Data Clasees di sini.
Codelab Data Classes
- Sebelum membuat obyek parcelable, kita buat kelas Java POJO terlebih dahulu. Caranya, klik kanan pada package utama → New → Kotlin File/Class (untuk Kotlin) atau package utama → New → Java Class (untuk Java)
- Pada dialog isikan nama kelas dengan Person’ dan pilih Kind dengan Class. Lalu klik OK.
- Setelah selesai terbentuk kelas Person, kondisikan kelas tersebut menjadi seperti ini
- data class Person(
- val name: String?,
- val age: Int?,
- val email: String?,
- val city: String?
- )
- public class Person{
- private String name;
- private int age;
- private String email;
- private String city;
- public Person(){
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- public String getEmail() {
- return email;
- }
- public void setEmail(String email) {
- this.email = email;
- }
- public String getCity() {
- return city;
- }
- public void setCity(String city) {
- this.city = city;
- }
- }
- Untuk yang menggunakan Java, Anda tak perlu menulis satu demi satu metode setter-getter nya. Android Studio sudah menyediakan fasilitas generator untuk hal tersebut. Caranya, setelah Anda menentukan variabel apa saja yang akan digunakan, lakukan beberapa langkah sebagai berikut:
Klik kanan pada workspace, pilih Generate (Alt+Insert) → Pilih Getter and Setter.
Pilih semua variabel dengan cara Ctrl+A pada windows atau Command+A pada mac.
Codelab Intent Explicit dengan Parcelable
Seperti yang diketahui bahwa di dalam Intent kita dapat menyisipkan data dengan tipe-tipe tertentu seperti string, int, double pada Intent. Tetapi tidak dengan tipe kompleks seperti objek, ArrayList, dll. Di sinilah peran besar Parcelable. Parcelable adalah suatu interface yang memungkinkan kita melakukan pengiriman objek dari suatu activity ke activity lain. Obyek yang di implementasikan dengan parcelable akan memudahkan Anda dalam mengiriman data dari satu activity ke activity lainnya.
Kali ini Anda akan mengubah kelas Person menjadi obyek parcelable.
- Implementasikan parcelable di kelas Person
- data class Person(
- val name: String?,
- val age: Int?,
- val email: String?,
- val city: String?
- ) : Parcelable
- public class Person implements Parcelable {
- private String name;
- private int age;
- private String email;
- private String city;
- ...
- }
- Akan muncul tanda merah, namun jangan khawatir, Anda hanya perlu arahkan kursor ke bagian nama kelas Person, kemudian tekan Alt+Enter atau bisa juga klik pada lampu merah, kemudian pilih Add Parcelable Implementation.
- Sekarang Anda bisa menemukan beragam metode parcelable untuk kelas Person. Sekarang kelas Person sudah sah menjadi kelas parcelable dan dapat dikirimkan ke activity lain melalui Intent. Maka, kelas Person menjadi seperti ini:
- data class Person(
- val name: String?,
- val age: Int?,
- val email: String?,
- val city: String?
- ) : Parcelable {
- constructor(parcel: Parcel) : this(
- parcel.readString(),
- parcel.readValue(Int::class.java.classLoader) as? Int,
- parcel.readString(),
- parcel.readString()) {
- }
- override fun writeToParcel(parcel: Parcel, flags: Int) {
- parcel.writeString(name)
- parcel.writeValue(age)
- parcel.writeString(email)
- parcel.writeString(city)
- }
- override fun describeContents(): Int {
- return 0
- }
- companion object CREATOR : Parcelable.Creator<Person> {
- override fun createFromParcel(parcel: Parcel): Person {
- return Person(parcel)
- }
- override fun newArray(size: Int): Array<Person?> {
- return arrayOfNulls(size)
- }
- }
- }
- public class Person implements Parcelable {
- private String name;
- private int age;
- private String email;
- private String city;
- public Person(){
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- public String getEmail() {
- return email;
- }
- public void setEmail(String email) {
- this.email = email;
- }
- public String getCity() {
- return city;
- }
- public void setCity(String city) {
- this.city = city;
- }
- protected Person(Parcel in) {
- name = in.readString();
- age = in.readInt();
- email = in.readString();
- city = in.readString();
- }
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(name);
- dest.writeInt(age);
- dest.writeString(email);
- dest.writeString(city);
- }
- @Override
- public int describeContents() {
- return 0;
- }
- public static final Creator<Person> CREATOR = new Creator<Person>() {
- @Override
- public Person createFromParcel(Parcel in) {
- return new Person(in);
- }
- @Override
- public Person[] newArray(int size) {
- return new Person[size];
- }
- };
- }
Sekarang waktunya kita implementasikan pada Intent. Namun sebelumnya, tambahkan satu tombol lagi pada activity_main.xml sebagai berikut:
- <Button
- android:id="@+id/btn_move_activity_object"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="16dp"
- android:text="@string/move_with_object" />
Sehingga activity_main.xml kita menjadi sebagai berikut:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:padding="16dp">
- <Button
- android:id="@+id/btn_move_activity"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="16dp"
- android:text="@string/move_activity" />
- <Button
- android:id="@+id/btn_move_activity_data"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="16dp"
- android:text="@string/move_with_data" />
- <Button
- android:id="@+id/btn_move_activity_object"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="16dp"
- android:text="@string/move_with_object" />
- </LinearLayout>
Setelah selesai dengan layout, kini kita kenalkan button tersebut di kelas MainActivity
- ...
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_main)
- ...
- val btnMoveWithObject:Button = findViewById(R.id.btn_move_activity_object)
- btnMoveWithObject.setOnClickListener(this)
- }
- ...
- ...
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- ...
- Button btnMoveWithObject = findViewById(R.id.btn_move_activity_object);
- btnMoveWithObject.setOnClickListener(this);
- }
- ...
- Buat activity baru dengan nama MoveWithObjectActivity.
- Kemudian pada layout activity_move_with_object.xml tambahkan satu textview untuk menampilkan data yang dikirimkan.
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:padding="16dp">
- <TextView
- android:id="@+id/tv_object_received"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/object_received" />
- </RelativeLayout>
- Sekarang kita kenalkan textview pada MoveWithObjectActivity tambahkan kodenya sehingga menjadi sebagai berikut:
- class MoveWithObjectActivity : AppCompatActivity() {
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_move_with_object)
- val tvObject:TextView = findViewById(R.id.tv_object_received)
- }
- }
- public class MoveWithObjectActivity extends AppCompatActivity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_move_with_object);
- TextView tvObject = findViewById(R.id.tv_object_received);
- }
- }
Selanjutnya pada kelas MoveWithObjectActivity kita tambahkan kode untuk menerima obyek dari activity Asal.
- class MoveWithObjectActivity : AppCompatActivity() {
- companion object {
- const val EXTRA_PERSON = "extra_person"
- }
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_move_with_object)
- val tvObject:TextView = findViewById(R.id.tv_object_received)
- val person = intent.getParcelableExtra(EXTRA_PERSON) as Person
- val text = "Name : ${person.name.toString()},\nEmail : ${person.email},\nAge : ${person.age},\nLocation : ${person.city}"
- tvObject.text = text
- }
- }
- public class MoveWithObjectActivity extends AppCompatActivity {
- public static final String EXTRA_PERSON = "extra_person";
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_move_with_object);
- TextView tvObject = findViewById(R.id.tv_object_received);
- Person person = getIntent().getParcelableExtra(EXTRA_PERSON);
- String text = "Name : " + person.getName() + ",\nEmail : " + person.getEmail() + ",\nAge : " + person.getAge() + ",\nLocation : " + person.getCity();
- tvObject.setText(text);
- }
- }
Setelah kita membuat activity tujuan, kini saatnya tambahkan beberapa baris kode pada bagian switch… case di MainActivity.
- override fun onClick(v: View) {
- when (v.id) {
- ...
- R.id.btn_move_activity_object -> {
- val person = Person(
- "DicodingAcademy",
- 5,
- "academy@dicoding.com",
- "Bandung"
- )
- val moveWithObjectIntent = Intent(this@MainActivity, MoveWithObjectActivity::class.java)
- moveWithObjectIntent.putExtra(MoveWithObjectActivity.EXTRA_PERSON, person)
- startActivity(moveWithObjectIntent)
- }
- }
- }
- @Override
- public void onClick(View v) {
- switch (v.getId()){
- ...
- case R.id.btn_move_activity_object:
- Person person = new Person();
- person.setName("DicodingAcademy");
- person.setAge(5);
- person.setEmail("academy@dicoding.com");
- person.setCity("Bandung");
- Intent moveWithObjectIntent = new Intent(MainActivity.this, MoveWithObjectActivity.class);
- moveWithObjectIntent.putExtra(MoveWithObjectActivity.EXTRA_PERSON, person);
- startActivity(moveWithObjectIntent);
- break;
- }
- }
Sehingga kode MainActivity kita menjadi sebagai berikut
- class MainActivity : AppCompatActivity(), View.OnClickListener {
- companion object {
- private const val REQUEST_CODE = 100
- }
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_main)
- val btnMoveActivity:Button = findViewById(R.id.btn_move_activity)
- btnMoveActivity.setOnClickListener(this)
- val btnMoveWithDataActivity:Button = findViewById(R.id.btn_move_activity_data)
- btnMoveWithDataActivity.setOnClickListener(this)
- val btnMoveWithObject:Button = findViewById(R.id.btn_move_activity_object)
- btnMoveWithObject.setOnClickListener(this)
- }
- override fun onClick(v: View) {
- when (v.id) {
- R.id.btn_move_activity -> {
- val moveIntent = Intent(this@MainActivity, MoveActivity::class.java)
- startActivity(moveIntent)
- }
- R.id.btn_move_activity_data -> {
- val moveWithDataIntent = Intent(this@MainActivity, MoveWithDataActivity::class.java)
- moveWithDataIntent.putExtra(MoveWithDataActivity.EXTRA_NAME, "DicodingAcademy Boy")
- moveWithDataIntent.putExtra(MoveWithDataActivity.EXTRA_AGE, 5)
- startActivity(moveWithDataIntent)
- }
- R.id.btn_move_activity_object -> {
- val person = Person(
- "DicodingAcademy",
- 5,
- "academy@dicoding.com",
- "Bandung"
- )
- val moveWithObjectIntent = Intent(this@MainActivity, MoveWithObjectActivity::class.java)
- moveWithObjectIntent.putExtra(MoveWithObjectActivity.EXTRA_PERSON, person)
- startActivity(moveWithObjectIntent)
- }
- }
- }
- }
- public class MainActivity extends AppCompatActivity implements View.OnClickListener{
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- Button btnMoveActivity = findViewById(R.id.btn_move_activity);
- btnMoveActivity.setOnClickListener(this);
- Button btnMoveWithDataActivity = findViewById(R.id.btn_move_activity_data);
- btnMoveWithDataActivity.setOnClickListener(this);
- Button btnMoveWithObject = findViewById(R.id.btn_move_activity_object);
- btnMoveWithObject.setOnClickListener(this);
- }
- @Override
- public void onClick(View v) {
- switch (v.getId()){
- case R.id.btn_move_activity:
- Intent moveIntent = new Intent(MainActivity.this, MoveActivity.class);
- startActivity(moveIntent);
- break;
- case R.id.btn_move_activity_data:
- Intent moveWithDataIntent = new Intent(MainActivity.this, MoveWithDataActivity.class);
- moveWithDataIntent.putExtra(MoveWithDataActivity.EXTRA_NAME, "DicodingAcademy Boy");
- moveWithDataIntent.putExtra(MoveWithDataActivity.EXTRA_AGE, 5);
- startActivity(moveWithDataIntent);
- break;
- case R.id.btn_move_activity_object:
- Person person = new Person();
- person.setName("DicodingAcademy");
- person.setAge(5);
- person.setEmail("academy@dicoding.com");
- person.setCity("Bandung");
- Intent moveWithObjectIntent = new Intent(MainActivity.this, MoveWithObjectActivity.class);
- moveWithObjectIntent.putExtra(MoveWithObjectActivity.EXTRA_PERSON, person);
- startActivity(moveWithObjectIntent);
- break;
- }
- }
- }
- Setelah semua komponen selesai dibuat, saatnya menjalankan kembali aplikasinya. Cobalah menakan tombol Pindah Activity dengan Object. Sekarang Anda sudah berhasil memindahkan satu obyek secara utuh, Selamat!
- Jika anda menggunakan bahasa Kotlin, ada fitur untuk membuat kelas Parcelable dengan lebih simpel dan tidak terlalu banyak kode hasil dari Add Implementation Parcelable, yaitu dengan menggunakan anotasi Parcelize. Untuk menambahkan parcelize Anda perlu mengikuti langkah-langkah berikut:
- Tambahkan kode berikut di build.gradle (module: app)di bawah apply plugin sebelum tag Android, sesuaikan juga urutan apply plugin di atasnya.
- apply plugin: 'com.android.application'
- apply plugin: 'kotlin-android'
- apply plugin: 'kotlin-android-extensions'
- androidExtensions {
- experimental = true
- }
- android {
- ...
- }
- Kemudian Anda hanya perlu menambahkan anotasi @Parcelizedi atas kelas model yang sudah diimplementasikan parcelable, maka hasil dan perbedaannya dapat Anda lihat pada kode berikut:
- Tambahkan kode berikut di build.gradle (module: app)di bawah apply plugin sebelum tag Android, sesuaikan juga urutan apply plugin di atasnya.
- @Parcelize
- data class Person(
- val name: String?,
- val age: Int?,
- val email: String?,
- val city: String?
- ) : Parcelable
- data class Person(
- val name: String?,
- val age: Int?,
- val email: String?,
- val city: String?
- ) : Parcelable {
- constructor(parcel: Parcel) : this(
- parcel.readString(),
- parcel.readValue(Int::class.java.classLoader) as? Int,
- parcel.readString(),
- parcel.readString()) {
- }
- override fun writeToParcel(parcel: Parcel, flags: Int) {
- parcel.writeString(name)
- parcel.writeValue(age)
- parcel.writeString(email)
- parcel.writeString(city)
- }
- override fun describeContents(): Int {
- return 0
- }
- companion object CREATOR : Parcelable.Creator<Person> {
- override fun createFromParcel(parcel: Parcel): Person {
- return Person(parcel)
- }
- override fun newArray(size: Int): Array<Person?> {
- return arrayOfNulls(size)
- }
- }
- }
Bedah Kode
Akhirnya Anda sudah berhasil menerapkan 3 tipe perpindahan Activity secara eksplisit melalui intent. Sekarang, mari kita dalami penjelasannya satu per satu.
Put Parcelable
- val person = Person(
- "DicodingAcademy",
- 5,
- "academy@dicoding.com",
- "Bandung"
- )
- Person person = new Person();
- person.setName("DicodingAcademy");
- person.setAge(5);
- person.setEmail("academy@dicoding.com");
- person.setCity("Bandung");
Di atas kita menciptakan sebuah obyek Person bernama person yang mana kelas tersebut adalah Parcelable. Kita atur semua data sesuai dengan propertinya. Kemudian kita akan mengirimkan obyek tersebut ke MoveWithObjectActivity melalui sebuah intent di bawah ini:
- val moveWithObjectIntent = Intent(this@MainActivity, MoveWithObjectActivity::class.java)
- moveWithObjectIntent.putExtra(MoveWithObjectActivity.EXTRA_PERSON, person)
- startActivity(moveWithObjectIntent)
- Intent moveWithObjectIntent = new Intent(MainActivity.this, MoveWithObjectActivity.class);
- moveWithObjectIntent.putExtra(MoveWithObjectActivity.EXTRA_PERSON, person);
- startActivity(moveWithObjectIntent);
Metode putExtra() yang kita pilih saat ini adalah putExtra(String name, Parcelable value).
Get Parcelable
EXTRA_PERSON merupakan variabel static bertipe data string dan bernilai “extra_person”. Berfungsi sebagai key untuk mendapatkan value data yang dikirim
Selanjutnya pada MoveWithObjectActivity kita akan mengambil nilai seperti berikut:
- val person = intent.getParcelableExtra(EXTRA_PERSON) as Person
- Person person = getIntent().getParcelableExtra(EXTRA_PERSON);
Dan ini yang seru. Karena obyek ini terdiri dari beragam tipe data pada atribut atau propertinya, kita hanya cukup membungkus itu semua ke dalam obyek parcelable.
Melalui getIntent().getParcelableExtra(Key), Anda dapat mengambil nilai obyek person yang sebelumnya telah dikirim hanya dengan satu variabel, bayangkan jika kita tidak menggunakan parcelable, maka kita harus mengirim data satu per satu. Jika datanya sedikit mungkin tidak masalah tapi jika datanya puluhan, tentu akan merepotkan kan?
Selanjutnya kita dapat menampilkan data obyek yang sudah diterima seperti ini:
- val text = "Name : ${person.name.toString()},\nEmail : ${person.email},\nAge : ${person.age},\nLocation : ${person.city}"
- tvObject.text = text
- String text = "Name : "+person.getName()+", Email : "+person.getEmail()+", Age : "+person.getAge() + ", Location : "+person.getCity();
- tvObject.setText(text);
Rows of Data
Lalu, bagaimana jika kita ingin mengirimkan kumpulan obyek parcelable ke activity lain? Untuk mengirimkan kumpulan data, kita bisa memanfaatkan arraylist dan metode putParcelableArrayListExtra.
Contoh kode ketika put extra adalah seperti ini:
- var persons = ArrayList<Person>()
- ...
- moveWithObjectIntent.putParcelableArrayListExtra(KEY,persons);
- ArrayList<Person> persons = new ArrayList<>();
- ...
- moveWithObjectIntent.putParcelableArrayListExtra(KEY,persons);
Dan ketika mengambil kumpulan datanya, kita bisa menggunakan kode ini:
- var persons = intent.getParcelableArrayListExtra(KEY) as ArrayList<Person>
- ArrayList<Person> persons = getIntent().getParcelableArrayListExtra(KEY);
Parcelize (Khusus Kotlin)
- apply plugin: 'com.android.application'
- apply plugin: 'kotlin-android'
- apply plugin: 'kotlin-android-extensions'
- androidExtensions {
- experimental = true
- }
- android {
- ...
- }
Parcelize adalah fitur yang masih bersifat experimental, untuk itulah di sini kita perlu mengaktifkan experimental di build.gradle(module: app) supaya bisa menggunakan fitur ini:
- @Parcelize
- data class Person(
- val name: String?,
- val age: Int?,
- val email: String?,
- val city: String?
- ) : Parcelable
Anotasi @Parcelize di atas nama kelas, digunakan untuk memberi tanda bahwa kelas ini yang dipilih untuk menjadi parcelable. @Parcelize juga otomatis men-generate semua kode yang digunakan untuk implemetasi parcelize sebelumnya.
Selamat, Anda sudah bisa mengirim obyek antar activity! Selanjutnya, kita akan membuat sebuah contoh aplikasi dengan menggunakan Intent Implicit