Android Parcelable

Merhaba, bu yazımda parcelable yapısını ve nasıl kullanıldığını anlatacağım.

Serializable

Bilindiği gibi Java’da Serializable interface’i, objeleri byte stream’e dönüştürür, böylece obje bir yerden başka bir yere aktarılabilir, fakat işlem sırasında Reflections kullanıldığı için bu interface yavaştır yani GC işlemi çoktur. Bu da pili aşırı tüketir. En güzel tarafı simple olmasıdır, çok hızlıca pojo’yu aktarıma hazır hale getirir.

import java.io.Serializable;
public class Person implements Serializable {
    // fields
    // constructors
    // getters & setters
}


Parcelable (smaller is better)

Parcelable ise Serializable’ın daha hızlı versiyonudur ve biraz daha kompleks bir yapıpya sahiptir. Memory işin içine girdiğinden Android içerisinde Parcelable kullanılır. Aşağıda Person sınıfı örneği verilmiştir ve sınıfın içinde Parcelable yapısı entegre edildikten sonra implement edilmesi gereken metotlar gösterilmiştir.

  • Sınıfımız Parcelable interface’ini miras alması gerekir.
  • public void writeToParcel(Parcel dest, int flags) : Oluşturulan objeyi string’e çevirir ve böylece intent içerisinde gönderilir. (Json’a serialize etmek gibi)
  • protected Person(Parcel in) : Gelen değerlerle yeni bir Person objesi oluşturarak döndürür. (Json’ı deserialize etmek gibi)
  • Generic creator: Gelen Parcel türündeki değişkeni yukardaki metodu çağırarak objeyi oluşturma işlemini gerçekleştirir. Parcelable.Creator interface’ini implement etmesi gerekir. Ayrıca metodun static final olarak tanımlanması gerekir.
  • public Person[] newArray(int size) : Bu karakterden array oluşturur.
  • public int describeContents() : 0 döndürür. (Metodu kullanmak zorundaysanız diye söyleyeyim, bu metot FileDescriptor’la ilgili işlem barındırır, low-level bir işlemdir diyebiliriz.) (Örnek kullanımı için buraya bakabilirsiniz.


Parcelable sınıf örneği:

import android.os.Parcel;
import android.os.Parcelable;
class Person implements Parcelable {

    // fields
    // constructors
    // getters & setters

  @Override
  public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(this.firstName);
    dest.writeString(this.lastName);
    dest.writeInt(this.age);
  }

  protected Person(Parcel in) {
    this.firstName = in.readString();
    this.lastName = in.readString();
    this.age = in.readInt();
  }

  public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() {
    @Override
    public Person createFromParcel(Parcel source) {
      return new Person(source);
    }

    @Override
    public Person[] newArray(int size) {
      return new Person[size];
    }
  };

    @Override
    public int describeContents() {
      return 0;
    }
}

Sınıfımı ve gerekli metotları oluşturdum. Peki bu sınıfın aktarım yolu nasıl olacak? MainActivity içerisinde p isimli Person değişkenim olsun. Bunu ben onSaveInstanceState metoduyla bundle içerisine kaydedip göndereceğim. Alırken de onCreate başında savedInstanceState yardımıyla değişkeni alacağım.

// Inside MainActivity we have a Person field variable p and we'll send it
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
  super.onSaveInstanceState(outState);
  outState.putParcelable("person" , p);
}
// and we're getting it
super.onCreate(savedInstanceState);
if(savedInstanceState!= null)
  p = savedInstanceState.getParcelable("person");
else { /* create new Person implementation */ }

Intent içerisinde yeni obje oluştururken gönderilmesi isteniyorsa Parcelable türüne cast edilmesi gerekmektedir, aşağıdaki gibi:

intent.putExtra("student", ((Parcelable)new Person("Mike","16")));

Kötü yönleri neler?
Parcelable yapısının hızlı olmasının yanında sakıncaları da vardır. Kod bir yerden sonra karmaşık bir hal alır, kod tekrarları oluşur ve sürdürebilirlik tehlikeye girer, ama söylediğim gibi memory sebebiyle smaller is better.

Serializable vs. Parcelable in Android

Android sisteminde ikisi kullanıldığında Parcelable 10 kat daha hızlı olduğunu buradan bulduğum örnekle aşağıdan görebilirsiniz.

Nexus 10
Serializable: 1.0004ms,  Parcelable: 0.0850ms – 10.16x improvement.

Nexus 4
Serializable: 1.8539ms – Parcelable: 0.1824ms – 11.80x improvement.

Desire Z
Serializable: 5.1224ms – Parcelable: 0.2938ms – 17.36x improvement.

Veya buradan bulduğum örnekle.

Burada ise diğer bir Serialization testini inceleyebilirsiniz.