Android: różnica między paczką a serializacją?


313

Dlaczego Android zapewnia 2 interfejsy do serializacji obiektów? Czy obiekty Bindernadające się do serializacji współpracują z plikami Androida i AIDL?

Odpowiedzi:


444

W Androidzie nie możemy po prostu przekazywać obiektów do działań. Aby to zrobić, obiekty muszą zostać zaimplementowane Serializablelub Parcelableinterfejs.

Serializowalny

Serializableto standardowy interfejs Java. Możesz po prostu zaimplementować Serializableinterfejs i dodać metody zastępowania. Problem z tym podejściem polega na tym, że stosuje się refleksję i jest to proces powolny. Ta metoda tworzy wiele tymczasowych obiektów i powoduje sporo śmiecia. Jednak Serializableinterfejs jest łatwiejszy do wdrożenia.

Spójrz na poniższy przykład (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");

Paczka

Parcelableproces jest znacznie szybszy niż Serializable. Jednym z powodów tego jest to, że mówimy wprost o procesie serializacji zamiast używać refleksji do wnioskowania. Ma również uzasadnienie, że kod został mocno zoptymalizowany do tego celu.

Spójrz na poniższy przykład (działki):

// 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");

Możesz przekazać ArrayListobiekty do paczkowania, jak poniżej:

// 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");

Wniosek

  1. Parcelablejest szybszy niż Serializableinterfejs
  2. ParcelableInterfejs wymaga więcej czasu na wdrożenie niż Serializableinterfejs
  3. Serializable interfejs jest łatwiejszy do wdrożenia
  4. Serializable Interfejs tworzy wiele tymczasowych obiektów i powoduje sporo śmiecia
  5. Parcelable tablica może być przekazywana przez Intent w Androidzie

2
@Sujith, co rozumiesz przez odbicie ? Co to jest odbicie ?
AnV

11
@AbhinavVutukuri Odbicie to termin sprawdzania obiektów, pól i metod w czasie wykonywania za pomocą Object.getClass () i tym podobnych.
FaultException

2
Serializable są lepsze do utrwalania danych, z drugiej strony nie można w ogóle utrwalać obiektów paczkowanych. To naprawdę zła praktyka
TheAnimatrix

2
@Sujith Jak stwierdziła więcej niż jedna osoba, obiektów paczkowatych nie można utrwalić (niezawodnie), ale można nadać im możliwość serializacji (w określonych granicach). Ponieważ twoja odpowiedź jest najwyżej punktowana i sprawia wrażenie pokrycia wszystkich ważnych różnic, prawdopodobnie powinieneś wspomnieć o tym.
LarsH

4
Teraz wdrożenie Parcelable jest tak szybkie, jak Serializable, wystarczy nacisnąć ALT + INSERT na dowolnej klasie implementującej Parcelable w Android Studio, a IDE to zrobi.
Ali Nem,

183

Serializable to standardowy interfejs Java. Po prostu zaznaczasz klasę Serializable, implementując interfejs, a Java automatycznie serializuje ją w określonych sytuacjach.

Parcelable to interfejs specyficzny dla Androida, w którym samodzielnie wdrażasz serializację. Został stworzony, aby być znacznie bardziej wydajnym niż Serializable i ominąć niektóre problemy z domyślnym schematem serializacji Java.

Uważam, że Binder i AIDL współpracują z obiektami paczkowalnymi.

Jednak można używać obiektów Serializowalnych w Intentach.


1
jak mogę serializować obiekt działki? Jak mogę to utrwalić?
Hades,

@Haded Pobierz zawartość stanu obiektów i zapisz ją w pliku lub bazie danych SQLLite. Seriliasing jest użyteczny do przenoszenia obiektów między różnymi komponentami w Androidzie lub w różnych aplikacjach.
Jonathan

6
To świetne wytłumaczenie. Zauważyłem również: „Paczka nie jest mechanizmem serializacji ogólnego zastosowania. Ta klasa (i odpowiadający jej Parcelable API do umieszczania dowolnych obiektów w paczce) jest zaprojektowany jako wysokowydajny transport IPC. Jako taki nie jest właściwe umieść dowolne dane Paczki w trwałym magazynie: zmiany w podstawowej implementacji dowolnych danych w Paczce mogą spowodować, że starsze dane będą nieczytelne. ” developer.android.com/reference/android/os/Parcel.html
Sam003

@Zhisheng co oznaczają dowolne obiekty? jakie przedmioty możemy umieścić w paczce?
hasnain_ahmad

Co powiesz na konwersję obiektów na ciąg json zamiast za pomocą gson?
FOO,

57

Paczkowany vs Serializowalny Odnoszę te dwa.

Dla Javy i Kotlin

1) Java

Serializowalny, prostota

Co to jest Serializowalny?

Serializable to standardowy interfejs Java. Nie jest częścią zestawu Android SDK. Jego prostota to piękno. Po wdrożeniu tego interfejsu Twoje POJO będzie gotowe do przejścia z jednej Aktywności do drugiej.

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;
}
}
  • Zaletą serializacji jest to, że wystarczy zaimplementować interfejs Serializable na klasie i jej dzieciach. Jest to interfejs znaczników, co oznacza, że ​​nie ma metody implementacji, Java po prostu dołoży wszelkich starań, aby skutecznie serializować go.

  • Problem z tym podejściem polega na tym, że stosuje się refleksję i jest to proces powolny. Mechanizm ten ma również tendencję do tworzenia wielu tymczasowych obiektów i powodowania sporo śmieci.

Przesyłki, prędkość

Co to jest paczka?

Parcelable to kolejny interfejs. Pomimo rywalizacji (Serializable, jeśli zapomniałeś), jest częścią zestawu Android SDK. Teraz Parcelable został specjalnie zaprojektowany w taki sposób, aby podczas użytkowania nie było odbicia. Wynika to z tego, że jesteśmy bardzo szczerzy w procesie serializacji.

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];
    }
};
}

Teraz zwycięzcą jest

wprowadź opis zdjęcia tutaj

Wyniki testów przeprowadzonych przez Philippe'a Breaulta pokazują, że paczka jest ponad 10 razy szybsza niż Serializable. Za tym stwierdzeniem stoją także inni inżynierowie Google.

Według nich domyślne podejście Serializowalne jest wolniejsze niż działki paczkowane. I tutaj mamy porozumienie między obiema stronami! ALE, porównywanie tych dwóch jest niesprawiedliwe! Ponieważ w Parcelable piszemy niestandardowy kod. Kod stworzony specjalnie dla tego jednego POJO. W ten sposób nie są tworzone śmieci, a wyniki są lepsze. Ale przy domyślnym podejściu Serializowalnym polegamy na automatycznym procesie serializacji Java. Proces ten najwyraźniej wcale nie jest niestandardowy i powoduje mnóstwo śmieci! Zatem gorsze wyniki.

Stop Stop !!!!, przed podjęciem decyzji

Teraz jest inne podejście . Cały automatyczny proces Serializable można zastąpić niestandardowym kodem, który wykorzystuje metody writeObject () i readObject (). Te metody są specyficzne. Jeśli chcemy polegać na podejściu Serializable w połączeniu z niestandardowym zachowaniem serializacji, musimy uwzględnić te dwie metody z taką samą dokładną sygnaturą, jak poniżej:

 private void writeObject(java.io.ObjectOutputStream out)
 throws IOException;

 private void readObject(java.io.ObjectInputStream in)
     throws IOException, ClassNotFoundException;

 private void readObjectNoData()
     throws ObjectStreamException;

A teraz porównanie między Paczkową a niestandardową Serializowalną wydaje się uczciwe! Wyniki mogą być zaskakujące! Niestandardowe podejście do szeregowania jest ponad 3-krotnie szybsze w przypadku zapisów i 1,6 razy szybsze w przypadku odczytów niż w przypadku paczek.

Edytowano: -----

2) Serializacja Kotlinx

Biblioteka Serialization Kotlinx

For Kotlin serialization need to add below dependency and plugin

implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.9.1"

apply plugin: 'kotlinx-serialization'

Twój build.gradleplik

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'
}

Serializacja odbywa się dość łatwo, należy opisać klasę przeznaczoną do niej @Serializableadnotacją jak poniżej

import kotlinx.serialization.Serializable
@Serializable
class Field {
    var count: Int = 0
    var name: String = ""
}

Dwie dodatkowe adnotacje do odnotowania to transienti optional. Użycie przejściowego spowoduje, że serializator zignoruje to pole, a użycie opcjonalnego pozwoli serializatorowi nie pęknąć, jeśli brakuje pola, ale jednocześnie należy podać wartość domyślną.

@Optional
var isOptional: Boolean = false
@Transient
var isTransient: Boolean = false

Uwaga : Może to również działać z klasami danych.

Teraz, aby faktycznie użyć tego w działaniu, weźmy przykład konwersji JSON na obiekt i odwrotnie

 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)
    }

Po więcej


@Farhana Jak to zrobić dla klasy danych w Kotlin?
Nisarg

@Nisarg Dodałem Kotlin Serialization, zobacz.
Farhana,

@Farhana To było bardzo wnikliwe. Naprawdę chcę przenieść się do Kotlin w pracy, ale moja propozycja jest ciągle odrzucana przez menedżerów. Zastanawiam się, czy mogę uzyskać test porównawczy dla Serializable (metodą niestandardową), który, jak mówisz, jest 1,6 razy szybszy niż Parcelable.
Abhinav Kulshreshtha

39

Jeśli chcesz być dobrym obywatelem, poświęć dodatkowy czas na wdrożenie paczkowania, ponieważ będzie działać 10 razy szybciej i zużyje mniej zasobów.

Jednak w większości przypadków spowolnienie Serializable nie będzie zauważalne. Możesz go używać, ale pamiętaj, że serializacja jest kosztowną operacją, więc ogranicz ją do minimum.

Jeśli próbujesz przekazać listę z tysiącami serializowanych obiektów, możliwe, że cały proces zajmie więcej niż sekundę. Może sprawić, że przejścia lub obrót z portretu do krajobrazu będą bardzo powolne.

Źródło do tego punktu: http://www.developerphil.com/parcelable-vs-serializable/


32

W Parcelable programiści piszą niestandardowy kod do zestawiania i rozpakowywania, dzięki czemu tworzy mniej obiektów śmieciowych w porównaniu do serializacji. Wydajność paczki nad serializacją znacznie się poprawia (około dwa razy szybciej) z powodu tej niestandardowej implementacji.

Serializable to interfejs znaczników, co oznacza, że ​​użytkownik nie może gromadzić danych zgodnie z ich wymaganiami. W serializacji operacja zestawiania jest wykonywana na wirtualnej maszynie Java (JVM) przy użyciu interfejsu API refleksji Java. Pomaga to zidentyfikować element członkowski i zachowanie obiektu Java, ale także powoduje powstanie wielu śmieci. Z tego powodu proces serializacji jest powolny w porównaniu do paczkowanego.

Edycja: Jakie znaczenie ma rozebranie i rozebranie?

W kilku słowach „marshalling” odnosi się do procesu konwersji danych lub obiektów w strumień bajtów, a „unmarshalling” jest odwrotnym procesem konwersji beack strumienia bajtów na ich oryginalne dane lub obiekt. Konwersja odbywa się poprzez „serializację”.

http://www.jguru.com/faq/view.jsp?EID=560072


Całkiem dobre wyjaśnienie, nawet bez pełnego przykładu. Właśnie tego potrzebowałem do zmiany.
sud007,

20

Właściwie to będę jedyną osobą, która będzie promować Serializable. Różnica prędkości nie jest już tak drastyczna, ponieważ urządzenia są znacznie lepsze niż kilka lat temu, a także istnieją inne, bardziej subtelne różnice. Aby uzyskać więcej informacji, zobacz mój blog na ten temat.


1
Dziękuję za udział. Jest mniej skomplikowany w implementacji serializacji i kompromis musi zostać ustalony w tych rzadkich przypadkach hiperoptymalizacji.
Ankan-Zerob

2
Alternatywny punkt widzenia, szczególnie gdy jest poparty eksperymentami i wynikami, jest bardzo pomocny. Muszę współpracować z wieloma istniejącymi kodami źródłowymi opartymi na paczkach i mogę je częściowo przerobić teraz, gdy przeczytałem twój post na blogu.
Les

14

Paczkowany jest swego rodzaju standardem w rozwoju Androida. Ale nie z powodu prędkości

Przesyłki zalecane są do przesyłania danych. Ale jeśli użyjesz serializowalnego poprawnie, jak pokazano w tym repozytorium , zobaczysz, że serializowalność jest czasem nawet szybsza niż pakowalna. Lub przynajmniej czasy są porównywalne.

Czy paczka jest szybsza niż seryjna?

Zwykła serializacja Java na przeciętnym urządzeniu z Androidem (jeśli jest wykonana poprawnie *) jest około 3,6 razy szybsza niż Parcelable dla zapisów i około 1,6 razy szybsza dla odczytów. Dowodzi to również, że serializacja Java (jeśli jest wykonana poprawnie) jest szybkim mechanizmem przechowywania, który daje akceptowalne wyniki nawet przy stosunkowo dużych wykresach obiektowych 11000 obiektów z 10 polami każdy.

* Teza jest taka, że ​​zwykle każdy, kto ślepo stwierdza, że ​​„paczka jest szybsza” porównuje ją do domyślnej automatycznej serializacji, która wykorzystuje dużo refleksji wewnątrz. Jest to niesprawiedliwe porównanie, ponieważ Parcelable korzysta z ręcznej (i bardzo skomplikowanej) procedury zapisywania danych do strumienia. Zazwyczaj nie wspomina się o tym, że standardowy Java Serializable zgodnie z dokumentami można również wykonać ręcznie, używając metod writeObject () i readObject (). Aby uzyskać więcej informacji, zobacz JavaDocs. Tak należy zrobić, aby uzyskać najlepszą wydajność.

Jeśli więc serializacja jest szybsza i łatwiejsza do wdrożenia, to dlaczego android ma w ogóle paczkę?

Powodem jest kod macierzysty. Paczka jest tworzona nie tylko do komunikacji międzyprocesowej. Może być również używany do komunikacji między kodami . Możesz wysyłać i odbierać obiekty z macierzystej warstwy C ++. Otóż ​​to.

Co wybrać Oba będą działać dobrze. Ale myślę, że Parcelable jest lepszym wyborem, ponieważ jest polecany przez Google i jak widać z tego wątku, jest o wiele bardziej doceniany.


Czy możesz umieścić swoje źródła? Byłbym bardzo wdzięczny. Dzięki!!
Archie G. Quiñones,

2
Taką odpowiedź otrzymałem od doświadczonego programisty, który pracuje nad projektem związanym z AOSP twitter.com/bwdude . Powiedział, że natywny kod C ++ do komunikacji z warstwą SDK wykorzystuje własną implementację Parcelable. Myślę, że mówi o tej klasie android.googlesource.com/platform/frameworks/native/+/ ... Wiem, że to nie jest najlepsze wytłumaczenie, ale najlepsze, jakie mam teraz. Jeśli znajdziesz coś jeszcze, koniecznie opublikuj to tutaj =)
Maksim Turaev,

Chciałbym móc cię głosować więcej niż raz. Widziałem świetnych ekspertów od Androida i Javy, którzy szukają najbardziej pozytywnej odpowiedzi tutaj. Brak dokumentacji naprawdę uniemożliwił pojawienie się jakiegokolwiek światła w Serializable. Wydaje się, że są to efekty promowania konkretnego interfejsu API. Dzięki!
pulp_fiction

11

1. Serializowalny

@ patrz http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html

Interfejs czego?

  • to standardowy interfejs Java

Prędkość

  • wolniejszy niż paczkowy

2. Paczkowany

@ patrz http://developer.android.com/reference/android/os/Parcelable.html

Interfejs czego?

  • jest interfejs android.os
    • co oznacza, że ​​Google opracował działkę paczkową, aby poprawić wydajność na Androidzie

Prędkość

  • szybciej (ponieważ jest zoptymalizowany do użycia w programowaniu Androida)

> Podsumowując

Należy pamiętać, że Serializable to standardowy interfejs Java, a Parcelable jest przeznaczony do programowania na Androida


Powinieneś także dodać ich zastosowania.
Anshul Tyagi,


4

Wdrożenie paczki może być szybsze, jeśli użyjesz wtyczki Paracelable w Android Studio. wyszukaj generator kodu działki na Androida


3

Interfejs Serializable może być używany w ten sam sposób, co interfejs Parcelable, co daje (niewiele) lepsze wyniki. Wystarczy zastąpić te dwie metody obsługi ręcznego zestawiania i rozpakowywania:

private void writeObject(java.io.ObjectOutputStream out)
    throws IOException
private void readObject(java.io.ObjectInputStream in)
    throws IOException, ClassNotFoundException

Wydaje mi się jednak, że przy opracowywaniu natywnego Androida, najlepszym rozwiązaniem jest użycie interfejsu API Androida.

Widzieć :


2

Spóźniam się z odpowiedzią, ale piszę z nadzieją, że pomoże to innym.

Jeśli chodzi o szybkość , Parcelable > Serializable. Ale niestandardowe serializowanie jest wyjątkiem. Jest prawie w zasięgu paczki lub nawet szybciej.

Odniesienie: https://www.geeksforgeeks.org/customized-serialization-and-deserialization-in-java/

Przykład:

Klasa niestandardowa do serializacji

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
    }

}


1

możesz użyć obiektów możliwych do serializacji w zamierzeniu, ale w momencie serializacji obiektu Parcelable może dać poważny wyjątek, taki jak NotSerializableException. Czy nie jest zalecane używanie serializowalnego z paczkowanym. Dlatego lepiej jest rozszerzyć działkę paczkową o obiekt, którego chcesz użyć z pakietem i zamiarami. Ponieważ ten działka jest specyficzny dla Androida, więc nie ma żadnych skutków ubocznych. :)


0

Serializowalny

Serializable to interfejs oznaczalny lub możemy go wywołać jako pusty interfejs. Nie ma żadnych wcześniej zaimplementowanych metod. Serializable zamierza przekonwertować obiekt na strumień bajtów. Użytkownik może więc przekazywać dane między jednym działaniem a drugim. Główną zaletą serializacji jest tworzenie i przekazywanie danych jest bardzo łatwe, ale jest to proces powolny w porównaniu do paczkowania.

Paczka

Usługa paczkowania jest szybsza niż możliwość serializacji. Działka paczkowa zamierza przekonwertować obiekt na strumień bajtów i przekazać dane między dwoma działaniami. Pisanie paczkowego kodu jest trochę skomplikowane w porównaniu do serializacji. Nie tworzy więcej obiektów tymczasowych podczas przekazywania danych między dwoma działaniami.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.