Android neden nesneleri serileştirmek için 2 arayüz sağlıyor? Serileştirilebilir nesneler Android Binder
ve AIDL dosyalarıyla birlikte çalışır mı?
Android neden nesneleri serileştirmek için 2 arayüz sağlıyor? Serileştirilebilir nesneler Android Binder
ve AIDL dosyalarıyla birlikte çalışır mı?
Yanıtlar:
Android'de nesneleri yalnızca etkinliklere aktaramayız. Bunu yapmak için nesnelerin ya uygulanması Serializable
ya da Parcelable
arabirimi olmalıdır .
Serileştirilebilir
Serializable
standart bir Java arayüzüdür. Sadece Serializable
arayüzü uygulayabilir ve geçersiz kılma yöntemleri ekleyebilirsiniz. Bu yaklaşımdaki sorun, yansımanın kullanılması ve yavaş bir süreç olmasıdır. Bu yöntem çok sayıda geçici nesne oluşturur ve biraz çöp toplanmasına neden olur. Ancak, Serializable
arayüzün uygulanması daha kolaydır.
Aşağıdaki örneğe bakın (Serializable):
// MyObjects Serializable class
import java.io.Serializable;
import java.util.ArrayList;
import java.util.TreeMap;
import android.os.Parcel;
import android.os.Parcelable;
public class MyObjects implements Serializable {
private String name;
private int age;
public ArrayList<String> address;
public MyObjects(String name, int age, ArrayList<String> address) {
super();
this.name = name;
this.age = age;
this.address = address;
}
public ArrayList<String> getAddress() {
if (!(address == null))
return address;
else
return new ArrayList<String>();
}
public String getName() {
return name;
}
public String getAge() {
return age;
}
}
// MyObjects instance
MyObjects mObjects = new MyObjects("name", "age", "Address array here");
// Passing MyObjects instance via intent
Intent mIntent = new Intent(FromActivity.this, ToActivity.class);
mIntent.putExtra("UniqueKey", mObjects);
startActivity(mIntent);
// Getting MyObjects instance
Intent mIntent = getIntent();
MyObjects workorder = (MyObjects) mIntent.getSerializableExtra("UniqueKey");
Parcelable
Parcelable
süreç çok daha hızlı Serializable
. Bunun nedenlerinden biri, sonuç çıkarmak için yansıma kullanmak yerine serileştirme süreci hakkında açık olmamızdır. Ayrıca, kodun bu amaç için yoğun bir şekilde optimize edilmesinin nedeni de geçerlidir.
Aşağıdaki örneğe bakın (Parcelable):
// MyObjects Parcelable class
import java.util.ArrayList;
import android.os.Parcel;
import android.os.Parcelable;
public class MyObjects implements Parcelable {
private int age;
private String name;
private ArrayList<String> address;
public MyObjects(String name, int age, ArrayList<String> address) {
this.name = name;
this.age = age;
this.address = address;
}
public MyObjects(Parcel source) {
age = source.readInt();
name = source.readString();
address = source.createStringArrayList();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(age);
dest.writeString(name);
dest.writeStringList(address);
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
public ArrayList<String> getAddress() {
if (!(address == null))
return address;
else
return new ArrayList<String>();
}
public static final Creator<MyObjects> CREATOR = new Creator<MyObjects>() {
@Override
public MyObjects[] newArray(int size) {
return new MyObjects[size];
}
@Override
public MyObjects createFromParcel(Parcel source) {
return new MyObjects(source);
}
};
}
// MyObjects instance
MyObjects mObjects = new MyObjects("name", "age", "Address array here");
// Passing MyOjects instance
Intent mIntent = new Intent(FromActivity.this, ToActivity.class);
mIntent.putExtra("UniqueKey", mObjects);
startActivity(mIntent);
// Getting MyObjects instance
Intent mIntent = getIntent();
MyObjects workorder = (MyObjects) mIntent.getParcelableExtra("UniqueKey");
ArrayList
Parcelable nesnelerini aşağıdaki gibi geçirebilirsiniz :
// Array of MyObjects
ArrayList<MyObjects> mUsers;
// Passing MyOjects instance
Intent mIntent = new Intent(FromActivity.this, ToActivity.class);
mIntent.putParcelableArrayListExtra("UniqueKey", mUsers);
startActivity(mIntent);
// Getting MyObjects instance
Intent mIntent = getIntent();
ArrayList<MyObjects> mUsers = mIntent.getParcelableArrayList("UniqueKey");
Sonuç
Parcelable
Serializable
arayüzden daha hızlıParcelable
arabirimin uygulanması Serializable
arabirime kıyasla daha fazla zaman alırSerializable
arayüzün uygulanması daha kolaydır Serializable
arayüzü çok sayıda geçici nesne oluşturur ve biraz çöp toplanmasına neden olurParcelable
dizi android niyet yoluyla geçirilebilirSerializable standart bir Java arayüzüdür. Arayüzü uygulayarak Serializable sınıfını işaretlemeniz yeterlidir ve Java belirli durumlarda otomatik olarak serileştirir.
Parcelable , serileştirmeyi kendiniz uyguladığınız Android'e özgü bir arayüzdür. Serializable'dan çok daha verimli olması ve varsayılan Java serileştirme şemasındaki bazı sorunların üstesinden gelmek için yaratılmıştır.
Binder ve AIDL'nin Parcelable nesneleriyle çalıştığına inanıyorum.
Ancak, Serializable nesnelerini Intents içinde kullanabilirsiniz.
Parcelable vs Serializable Bu ikisinden söz ediyorum.
Java ve Kotlin için
1) Java
Serileştirilebilir, Basitlik
Serileştirilebilir nedir?
Serializable standart bir Java arayüzüdür. Android SDK'sının bir parçası değildir. Sadeliği güzelliğidir. Sadece bu arayüzü uygulayarak POJO'nuz bir Faaliyetten diğerine atlamaya hazır olacaktır.
public class TestModel implements Serializable {
String name;
public TestModel(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Serileştirilebilirliğin güzelliği, Serializable arabirimini bir sınıf ve çocuklarına uygulamanız gerektiğidir. Bir işaretleyici arabirimidir, yani uygulanacak bir yöntem yoktur, Java bunu verimli bir şekilde serileştirmek için elinden geleni yapacaktır.
Bu yaklaşımdaki sorun, yansımanın kullanılması ve yavaş bir süreç olmasıdır. Bu mekanizma ayrıca çok sayıda geçici nesne oluşturma ve biraz çöp toplanmasına neden olma eğilimindedir.
Parcelable, Hız
Parcelable nedir?
Parcelable başka bir arabirimdir. Rakibine rağmen (unutmanız halinde seri hale getirilebilir), Android SDK'nın bir parçasıdır. Şimdi, Parcelable, kullanıldığında herhangi bir yansıma olmayacak şekilde özel olarak tasarlanmıştır. Bunun nedeni serileştirme süreci için gerçekten açık olmamızdır.
public class TestModel implements Parcelable {
String name;
public TestModel(String name, String id) {
this.name = name;
}
protected TestModel(Parcel in) {
this.name = in.readString();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.name);
}
public static final Parcelable.Creator<TestModel> CREATOR = new Parcelable.Creator<TestModel>() {
@Override
public TestModel createFromParcel(Parcel source) {
return new TestModel(source);
}
@Override
public TestModel[] newArray(int size) {
return new TestModel[size];
}
};
}
Şimdi kazanan
Philippe Breault tarafından yapılan testlerin sonuçları, Parcelable'ın Serializable'dan 10 kat daha hızlı olduğunu gösteriyor. Diğer bazı Google mühendisleri de bu ifadenin arkasında duruyor.
Onlara göre, varsayılan Serileştirilebilir yaklaşım Parcelable'dan daha yavaştır. Ve burada iki taraf arasında bir anlaşmamız var! AMA, bu ikisini karşılaştırmak haksızlık! Çünkü Parcelable ile özel kod yazıyoruz. Bu özel POJO için özel olarak oluşturulan kod. Böylece çöp oluşmaz ve sonuçlar daha iyi olur. Ancak, varsayılan Serializable yaklaşımıyla, Java'nın otomatik serileştirme sürecine güveniyoruz. Süreç hiç de özel değil ve çok fazla çöp yaratıyor! Böylece, daha kötü sonuçlar.
Dur Dur !!!!, karar vermeden önce
Şimdi başka bir yaklaşım var . Serializable'ın arkasındaki tüm otomatik işlem, writeObject () & readObject () yöntemlerini kullanan özel kod ile değiştirilebilir. Bu yöntemler spesifiktir. Serializable yaklaşımına özel serileştirme davranışı ile birlikte güvenmek istiyorsak, bu iki yöntemi aşağıdakiyle aynı imzayla dahil etmeliyiz:
private void writeObject(java.io.ObjectOutputStream out)
throws IOException;
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException;
private void readObjectNoData()
throws ObjectStreamException;
Ve şimdi Parcelable ve özel Serializable arasındaki bir karşılaştırma adil görünüyor! Sonuçlar şaşırtıcı olabilir! Özel Serileştirilebilir yaklaşım, yazma işlemleri için 3 kat ve okumalar için Parcelable'dan 1,6 kat daha hızlıdır.
Düzenlendi: -----
2) Kotlinx Serileştirmesi
Kotlinx Serileştirme Kütüphanesi
For Kotlin serialization need to add below dependency and plugin
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.9.1"
apply plugin: 'kotlinx-serialization'
Kişisel build.gradle
dosya
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlinx-serialization'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.example.smile.kotlinxretrosample"
minSdkVersion 16
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.9.1"
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'com.android.support:design:28.0.0'
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.squareup.okhttp3:okhttp:3.12.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
Serileştirme oldukça kolay bir şekilde yapılır, hedeflenen sınıfa @Serializable
aşağıdaki açıklama ekleyerek açıklama eklemeniz gerekir
import kotlinx.serialization.Serializable
@Serializable
class Field {
var count: Int = 0
var name: String = ""
}
Dikkat edilmesi gereken iki açıklama daha vardır transient
ve optional
. Geçici kullanıldığında, serileştiricinin bu alanı yoksayması ve isteğe bağlı kullanılması, bir alanın eksik olması durumunda serileştiricinin kırılmasına izin vermez, ancak aynı zamanda varsayılan bir değerin sağlanması gerekir.
@Optional
var isOptional: Boolean = false
@Transient
var isTransient: Boolean = false
Not : Bu, veri sınıflarıyla da çalışabilir.
Şimdi bunu aslında eylemde kullanmak için bir JSON'u nesneye ve geri dönüştürmek için bir örnek alalım
fun toObject(stringValue: String): Field {
return JSON.parse(Field.serializer(), stringValue)
}
fun toJson(field: Field): String {
//Notice we call a serializer method which is autogenerated from our class
//once we have added the annotation to it
return JSON.stringify(Field.serializer(), field)
}
Daha fazlası için
Serialization
, bir bakın.
İyi bir vatandaş olmak istiyorsanız, Parcelable'ı uygulamak için ekstra zaman ayırın çünkü 10 kat daha hızlı performans gösterecek ve daha az kaynak kullanacaktır.
Bununla birlikte, çoğu durumda, Serileştirilebilirliğin yavaşlığı fark edilmeyecektir. Kullanmaktan çekinmeyin, ancak serileştirmenin pahalı bir işlem olduğunu unutmayın, bu yüzden minimumda tutun.
Binlerce serileştirilmiş nesne içeren bir liste iletmeye çalışıyorsanız, tüm sürecin bir saniyeden fazla sürmesi mümkündür. Dikeyden peyzaja geçişleri veya dönüşü çok halsiz hissedebilir.
Bu noktaya kaynak: http://www.developerphil.com/parcelable-vs-serializable/
Parcelable'da, geliştiriciler sıralama ve sıralama için özel kod yazarlar, böylece Serileştirmeye kıyasla daha az çöp nesnesi oluştururlar. Serileştirilebilir Seri Üretim Üzerinden Performans, bu özel uygulama nedeniyle önemli ölçüde iyileşir (yaklaşık iki kat daha hızlı).
Serializable, kullanıcının verileri ihtiyaçlarına göre marshal edemeyeceğini gösteren bir işaretleyici arabirimidir. Serileştirme'de, Java yansıma API'sini kullanarak bir Java Sanal Makinesi (JVM) üzerinde bir marş işlemi gerçekleştirilir. Bu, Java nesnesinin üyesini ve davranışını tanımlamaya yardımcı olur, ancak aynı zamanda çok sayıda çöp nesnesi oluşturur. Bu nedenle, Serileştirme işlemi Parcelable ile karşılaştırıldığında yavaştır.
Edit: Marshmaling ve Marshallming anlamı nedir?
Birkaç kelime ile "marşaling", verilerin veya nesnelerin bir bayt-akışına dönüştürülmesi işlemini ifade eder ve "unmarshalling", byte-akış işaretinin orijinal verilerine veya nesnelerine dönüştürülmesi işleminin tersidir. Dönüşüm "serileştirme" ile gerçekleştirilir.
Aslında Serializable'ı savunan tek adam olacağım. Hız farkı artık çok şiddetli değil, çünkü cihazlar birkaç yıl öncesine göre çok daha iyi ve daha başka, daha ince farklılıklar var. Daha fazla bilgi için bu konudaki blog yayınımı görün .
Veri aktarımı için parcelable önerilir. Ancak bu repoda gösterildiği gibi doğru şekilde serileştirilebilir kullanırsanız repoda , serileştirilebilirliğin bazen ayrıştırılabilirden daha da hızlı olduğunu göreceksiniz. Ya da en azından zamanlamalar karşılaştırılabilir.
Ortalama bir Android cihazında (doğru yapılırsa) her zamanki Java serileştirmeleri, yazma için Parcelable'dan yaklaşık 3,6 kat ve okumalar için yaklaşık 1,6 kat daha hızlıdır. Ayrıca Java Serileştirmesinin (doğru yapılırsa), her biri 10 alana sahip 11000 nesnenin nispeten büyük nesne grafikleriyle bile kabul edilebilir sonuçlar veren hızlı depolama mekanizması olduğunu kanıtlar.
* Sidenote genellikle "Parcelable is mush daha hızlı" körü körüne söyleyen herkes, onu içinde çok fazla yansıma kullanan varsayılan otomatik serileştirme ile karşılaştırır. Parcelable, veriye veri yazmak için manuel (ve çok karmaşık) bir prosedür kullandığından, bu haksız bir karşılaştırmadır. Genellikle bahsedilmeyen şey, belgelere göre standart Serializable'ın writeObject () ve readObject () yöntemleri kullanılarak manuel olarak da yapılabileceğidir. Daha fazla bilgi için bkz. JavaDocs. En iyi performans için böyle yapılması gerekir.
Nedeni yerel kod. Parcelable, yalnızca süreçler arası iletişim için değil. Ayrıca intercode iletişimi için de kullanılabilir . C ++ yerel katmanından nesne gönderebilir ve alabilirsiniz. Bu kadar.
Ne seçmelisin? Her ikisi de iyi çalışır. Ancak Parcelable daha iyi bir seçim olduğunu düşünüyorum çünkü google tarafından tavsiye edilir ve bu iş parçacığından görebileceğiniz gibi çok daha takdir edilmektedir.
@görmek http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html
@görmek http://developer.android.com/reference/android/os/Parcelable.html
Serializable'ın standart bir Java arayüzü olduğunu ve Parcelable'ın Android Geliştirme için olduğunu unutmayın
Pazarlanma ve paylaşımsızlıkla ilgili bazı performans sorunları vardır. Parcelable, Serializable'dan iki kat daha hızlı.
Lütfen aşağıdaki bağlantıdan geçin:
http://www.3pillarglobal.com/insights/parcelable-vs-java-serialization-in-android-app-development
Serileştirilebilir arabirim, Parcelable arabirimi ile aynı şekilde kullanılabilir ve bu da (çok fazla) daha iyi performans sağlar. Manuel marşaling ve marşaldırma işlemini gerçekleştirmek için bu iki yöntemin üzerine yazmanız yeterlidir:
private void writeObject(java.io.ObjectOutputStream out)
throws IOException
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException
Yine de bana öyle geliyor ki, yerel Android geliştirirken, Android API'sini kullanmanın yolu var.
Görmek :
Yanıtta geç kaldım, ancak başkalarına yardımcı olacağını ümit ediyorum.
Açısından Hız , Parcelable > Serializable
. Ancak, Custom Serializable istisnadır. Neredeyse Parcelable aralığında veya daha da hızlı.
Referans: https://www.geeksforgeeks.org/customized-serialization-and-deserialization-in-java/
Misal :
Serileştirilecek Özel Sınıf
class MySerialized implements Serializable {
String deviceAddress = "MyAndroid-04";
transient String token = "AABCDS"; // sensitive information which I do not want to serialize
private void writeObject(ObjectOutputStream oos) throws Exception {
oos.defaultWriteObject();
oos.writeObject("111111" + token); // Encrypted token to be serialized
}
private void readObject(ObjectInputStream ois) throws Exception {
ois.defaultReadObject();
token = ((String) ois.readObject()).subString(6); // Decrypting token
}
}
Binder ile serileştirilenden çok daha hızlı ayrıştırılabilir, çünkü serileştirilebilir kullanım yansıması ve birçok GC'ye neden olur. Parcelable, nesneyi geçirmeyi optimize etmek için tasarlanmıştır.
İşte referans bağlantısı. http://www.developerphil.com/parcelable-vs-serializable/
serileştirilebilir nesneleri amaçlarda kullanabilirsiniz, ancak Parcelable nesnesini serileştirirken, NotSerializableException gibi ciddi bir istisna verebilir. Parcelable ile serileştirilebilir kullanılması önerilmez. Bu nedenle, paket ve amaçlarla kullanmak istediğiniz nesne ile Parcelable öğesini genişletmek daha iyidir. Bu Parcelable, android'e özgü olduğundan, herhangi bir yan etkisi yoktur. :)
Serileştirilebilir
Serializable belirgin bir arayüz veya boş bir arayüz olarak çağırabiliriz. Önceden uygulanmış herhangi bir yöntemi yoktur. Serializable bir nesneyi bayt akışına dönüştürecektir. Böylece kullanıcı verileri bir etkinlik arasında başka bir etkinliğe geçirebilir. Serileştirilebilirliğin ana avantajı, oluşturma ve veri aktarmanın çok kolay olması, ancak parcelable ile karşılaştırıldığında yavaş bir işlemdir.
Parcelable
Parsel mümkün serileştirilebilir daha hızlıdır. Parsel, nesneyi bayt akışına dönüştürecek ve verileri iki etkinlik arasında geçirecektir. Parsel mümkün kod yazmak serileştirmeye kıyasla biraz karmaşıktır. Verileri iki etkinlik arasında geçirirken daha fazla geçici nesne oluşturmaz.