Próbuję pracować nad wysłaniem obiektu mojej klasy klienta z jednego Activity
i wyświetlenia go w innym Activity
.
Kod dla klasy klienta:
public class Customer {
private String firstName, lastName, Address;
int Age;
public Customer(String fname, String lname, int age, String address) {
firstName = fname;
lastName = lname;
Age = age;
Address = address;
}
public String printValues() {
String data = null;
data = "First Name :" + firstName + " Last Name :" + lastName
+ " Age : " + Age + " Address : " + Address;
return data;
}
}
Chcę wysłać obiekt od jednego Activity
do drugiego, a następnie wyświetlić dane na drugim Activity
.
Jak mogę to osiągnąć?
Odpowiedzi:
Jedną z opcji może być pozwolenie klasie niestandardowej na implementację
Serializable
interfejsu, a następnie można przekazać instancje obiektów w zamiar za pomocąputExtra(Serializable..)
wariantuIntent#putExtra()
metody.Pseudokod :
Uwaga: Upewnij się, że każda zagnieżdżona klasa głównej klasy niestandardowej ma zaimplementowany interfejs Serializable, aby uniknąć wyjątków serializacji. Na przykład:
źródło
Parcelable
jest specjalnie zaprojektowany do tego celu (i znacznie szybciej niżSerializable
). Jestem zmieszany.Parcelable
może być dobre dla prędkości, ale jego wdrożenie jest skomplikowane. Co zrobić, jeśli masz 8 obiektów, które musisz przekazać między ćwiczeniami, czy zamierzasz wykonać każdy z nichParcelable
?Serializable
Zamiast tego lepiej byłoby użyć . Po wdrożeniuParcelable
musisz dodać dużo kodu do klasy i uporządkować pola w bardzo specyficzny sposób;Serializable
ty nie. Ostatecznie myślę, że sprowadza się to do tego, ile przedmiotów mijasz i co próbujesz zrobić.Serializable
to standardowy interfejs Java. Po prostu zaznaczasz klasę Serializable, implementując interfejs, a Java automatycznie serializuje go w określonych sytuacjach.Parcelable
jest interfejsem specyficznym dla systemu Android, 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 JavaZaimplementuj swoją klasę dzięki Serializable. Załóżmy, że to twoja klasa jednostek:
Wysyłamy obiekt wywołany
dene
z działania X do działania Y. Gdzieś w aktywności X;W aktywności Y otrzymujemy obiekt.
Otóż to.
źródło
classCastException: java.lang.Long
robię to. Czy możesz wyjaśnić dlaczego?(Serializable)
do obiektu?Za pomocą tej strony możesz wygenerować kod paczki dla swojej klasy .
źródło
Parcelable
, wolałbym, aby moje klasy POJO były niezależne od Androida i używaneSerializable
.Użyj gson, aby przekonwertować obiekt na JSON i przekazać go przez zamiar. W nowym działaniu przekonwertuj JSON na obiekt.
W swoim
build.gradle
dodaj to do swoich zależnościW swoim działaniu przekonwertuj obiekt na ciąg json:
W działaniu odbierającym przekonwertuj ciąg json z powrotem na oryginalny obiekt:
Dla Kotlina jest tak samo
Przekaż dane
Odbierz dane
źródło
Podczas dzwonienia do działania
W toClass.java otrzymaj aktywność przez
Upewnij się, że klasa klienta wdraża paczkę
źródło
Z mojego doświadczenia wynikają trzy główne rozwiązania, każde z ich wadami i zaletami:
Wdrażanie paczki
Wdrożenie serializowalne
Korzystanie z pewnego rodzaju lekkiej biblioteki magistrali zdarzeń (na przykład EventBus Greenrobota lub Otto Square)
Paczkowany - szybki i standardowy dla systemu Android, ale ma dużo kodu typu „płyta podstawowa” i wymaga ciągów znaków zakodowanych na stałe w celu wyciągnięcia wartości z zamiaru (nie jest mocno wpisany).
Serializowalny - bliski zerowej tablicy rejestracyjnej, ale jest to najwolniejsze podejście i wymaga również zakodowanych ciągów znaków podczas wyciągania wartości z zamiaru (niezbyt typowy).
Magistrala zdarzeń - zerowa płyta kotłowa, najszybsze podejście i nie wymaga zakodowanych ciągów, ale wymaga dodatkowej zależności (choć zwykle lekka, ~ 40 KB)
Opublikowałem bardzo szczegółowe porównanie dotyczące tych trzech podejść, w tym testów wydajności.
źródło
Znalazłem prostą i elegancką metodę:
Metoda 1
Kod pierwszego działania:
Kod drugiego działania:
znajdziesz
objSent
iobjReceived
masz to samohashCode
, więc są identyczne.Ale dlaczego możemy w ten sposób przekazać obiekt Java?
W rzeczywistości Android Binder utworzy globalne odwołanie JNI dla obiektu Java i zwolni to globalne odwołanie JNI, gdy nie będzie odniesienia do tego obiektu Java. binder zapisze to globalne odniesienie JNI w obiekcie Binder.
* UWAGA: ta metoda działa TYLKO, chyba że dwie czynności działają w tym samym procesie, w przeciwnym razie wyrzuć ClassCastException na (ObjectWrapperForBinder) getIntent (). GetExtras (). GetBinder („wartość_obiektu”) *
klasa Definiowanie obiektu ObjectWrapperForBinder
Metoda 2
Ale Metoda 2 ma mały, ale poważny problem, jeśli odbiornik nie przywróci obiektu java (na przykład zdarzy się jakiś wyjątek przed przywróceniem obiektu java lub działanie odbiorcy w ogóle nie istnieje), wówczas obiekt java stanie się wyciek sieroty lub pamięci, Metoda 1 nie ma tego problemu, ponieważ Android Binder poradzi sobie z tym wyjątkiem
Metoda 3
Aby zdalnie wywołać obiekt Java, utworzymy umowę / interfejs danych opisujący obiekt Java, użyjemy pliku aidl
IDataContract.aidl
Kod pierwszej aktywności
Kod drugiego działania:
zmień atrybut android: proces w AndroidManifest.xml na niepustą nazwę procesu, aby mieć pewność, że drugie działanie zostanie uruchomione w innym procesie
W ten sposób możemy przekazać interfejs między dwoma działaniami, nawet jeśli działają one w innym procesie, i wywołać metodę interfejsu zdalnie
Metoda 4
metoda 3 wydaje się nie dość prosta, ponieważ musimy wdrożyć interfejs pomocniczy. Jeśli chcesz po prostu wykonać proste zadanie, a wartość zwracana przez metodę jest niepotrzebna, możemy użyć android.os.Messenger
Kod pierwszego działania (nadawcy):
Kod drugiej czynności (odbiorcy):
Wszystkie Messenger.send będą wykonywane w module obsługi asynchronicznie i sekwencyjnie.
W rzeczywistości android.os.Messenger jest także interfejsem pomocniczym, jeśli masz kod źródłowy Androida, możesz znaleźć plik o nazwie IMessenger.aidl
źródło
Możesz również zapisać dane obiektu w tymczasowych ciągach znaków i liczbach wewnętrznych i przekazać je do działania. Oczywiście w ten sposób dostajesz dane, ale nie sam obiekt.
Ale jeśli chcesz je tylko wyświetlić, a nie używać obiektu w innej metodzie lub czegoś takiego, powinno wystarczyć. Zrobiłem to w ten sam sposób, aby wyświetlić dane z jednego obiektu w innym działaniu.
Możesz również przekazać je bezpośrednio zamiast temp ivars, ale w ten sposób jest to, moim zdaniem, wyraźniejsze. Dodatkowo możesz ustawić temp ivars na zero, aby szybciej zostały wyczyszczone przez GarbageCollector.
Powodzenia!
Na marginesie: zastąp toString () zamiast pisać własną metodę drukowania.
Jak wspomniano w komentarzach poniżej, w ten sposób odzyskujesz dane w innej działalności:
źródło
Bundle extras = getIntent().getExtras();
String val = extras.getString("fname");
Zrobiłem singletona klasę pomocniczą, która przechowuje przedmioty tymczasowe.
Zamiast umieszczać obiekty w obszarze Intent, użyj IntentHelper:
Wewnątrz nowej aktywności możesz uzyskać obiekt:
Pamiętaj, że po załadowaniu obiekt jest usuwany, aby uniknąć niepotrzebnych odniesień.
źródło
BookActivity.getInstance().recommendationResponse
inRoomsActivity
obj
staje sięnull
. Aby tego uniknąć,obj
należy go gdzieś przechowywać, aby uzyskać go ponownie. Rzeczywiście, rozwiązanie Json przechowuje dane obiektu w Intent.Istnieje kilka sposobów uzyskiwania dostępu do zmiennych lub obiektów w innych klasach lub działaniu.
A. Baza danych
B. Wspólne preferencje.
C. Serializacja obiektów.
D. Klasa, która może przechowywać wspólne dane, można nazwać Common Utilities. To zależy od Ciebie.
E. Przekazywanie danych przez intencje i interfejs paczkowany.
To zależy od potrzeb twojego projektu.
A. Baza danych
SQLite to baza danych typu open source wbudowana w system Android. SQLite obsługuje standardowe funkcje relacyjnej bazy danych, takie jak składnia SQL, transakcje i przygotowane wyciągi.
Poradniki
B. Wspólne preferencje
Załóżmy, że chcesz zapisać nazwę użytkownika. Będą teraz dwie rzeczy: kluczowa nazwa użytkownika, wartość wartości.
Jak przechowywać
Używając putString (), putBoolean (), putInt (), putFloat () i putLong () możesz zapisać żądany typ danych.
Jak pobrać
http://developer.android.com/reference/android/content/SharedPreferences.html
C. Serializacja obiektów
Serlizacja obiektów jest stosowana, jeśli chcemy zapisać stan obiektu, aby wysłać go przez sieć lub można go również użyć do własnych celów.
Używaj ziaren Java i przechowuj w nim jako jedno z jego pól i używaj do tego getters i setter.
JavaBeans to klasy Java, które mają właściwości. Traktuj właściwości jako zmienne instancji prywatnej. Ponieważ są prywatne, jedynym sposobem, aby uzyskać do nich dostęp spoza ich klasy, są metody w klasie. Metody zmieniające wartość właściwości nazywane są metodami ustawiającymi, a metody pobierające wartość właściwości nazywane są metodami pobierającymi.
Ustaw zmienną w metodzie poczty za pomocą
Następnie użyj serializacji obiektu, aby serializować ten obiekt, a w drugiej klasie deserializować ten obiekt.
W serializacji obiekt może być reprezentowany jako ciąg bajtów, który zawiera dane obiektu, a także informacje o typie obiektu i typach danych przechowywanych w obiekcie.
Po zapisaniu serializowanego obiektu w pliku można go odczytać z pliku i zserializować. Oznacza to, że informacje o typie i bajty reprezentujące obiekt oraz jego dane mogą zostać wykorzystane do odtworzenia obiektu w pamięci.
Jeśli chcesz samouczek do tego, zapoznaj się z:
Serializacja w Javie (post na blogu)
Uzyskaj zmienną w innych klasach (przepełnienie stosu)
D. Wspólne narzędzia
Możesz sam stworzyć klasę, która może zawierać wspólne dane, których często potrzebujesz w swoim projekcie.
Próba
E. Przekazywanie danych przez zamiary
Aby zapoznać się z tą opcją przekazywania danych, zapoznaj się z samouczkiem Android - Dane przesyłek, które należy przekazywać między działaniami korzystającymi z klas przesyłek .
źródło
Utwórz własną klasę
Customer
w następujący sposób:W twojej
onCreate()
metodzieNa
xyz activity
zajęciach musisz użyć następującego kodu:źródło
Najlepszym sposobem jest posiadanie w aplikacji klasy (nazywającej ją Kontrolą), która będzie przechowywać zmienną statyczną typu „Klient” (w twoim przypadku). Zainicjuj zmienną w swoim działaniu A.
Na przykład:
Następnie przejdź do działania B i pobierz go z klasy Control. Nie zapomnij przypisać wartości null po użyciu zmiennej, w przeciwnym razie pamięć zostanie zmarnowana.
źródło
Teraz chcesz przekazać obiekt tej klasy w startActivity. Po prostu użyj tego:
Działa to tutaj, ponieważ implementuje MyClass
Serializable
.źródło
Jeśli wybierzesz sposób, w jaki opisuje Samuh, pamiętaj, że można wysyłać tylko wartości pierwotne. To znaczy wartości, które można sparować. Jeśli więc Twój obiekt zawiera złożone obiekty, nie będą one stosowane. Na przykład zmienne takie jak Bitmap, HashMap itp. Trudno jest przejść przez zamiar.
W ogóle radziłbym Ci wysłać tylko prymitywne typy danych jako statystów, jak String, int, boolean itp w Twoim przypadku będzie to:
String fname
,String lname
,int age
, iString address
.Moja opinia: bardziej złożone obiekty są lepiej udostępniane przez implementację ContentProvider , SDCard itp. Możliwe jest również użycie zmiennej statycznej , ale może to szybko prowadzić do kodu podatnego na błędy ...
Ale znowu to tylko moja subiektywna opinia.
źródło
Używam paczkowatego do wysyłania danych z jednej aktywności do innej aktywności. Oto mój kod, który działa dobrze w moim projekcie.
W działaniu A użyj go w następujący sposób:
W ActivityB użyj go w ten sposób, aby uzyskać dane:
źródło
Możesz spróbować użyć tej klasy. Ograniczeniem jest to, że nie można go używać poza jednym procesem.
Jedna aktywność:
Inna działalność:
źródło
Rozpocznij inną aktywność od tej aktywności i przekaż parametry przez Obiekt pakietu
Odzyskaj dane z innego działania (YourActivity)
Jest to odpowiednie dla prostego rodzaju danych. Ale jeśli chcesz przekazywać złożone dane pomiędzy działaniami. Najpierw musisz serializować.
Tutaj mamy model pracownika
Możesz użyć biblioteki Gson lib dostarczonej przez Google do serializacji złożonych danych w ten sposób
źródło
To pytanie jest również omówione w innym pytaniu dotyczącym przepełnienia stosu. Zapoznaj się z rozwiązaniem problemu Przekazywanie danych przez zamiar za pomocą Serializable . Chodzi przede wszystkim o użycie
Bundle
obiektu, w którym przechowywane są niezbędne daneIntent
.Aby wyodrębnić wartości:
Zaletą
Serializable
jest jego prostota. Jednak powinieneś rozważyć użycieParcelable
metody, jeśli potrzebujesz wielu danych do przesłania, ponieważParcelable
jest specjalnie zaprojektowany dla Androida i jest bardziej wydajny niżSerializable
. Możesz stworzyćParcelable
zajęcia używając:źródło
Kreta jest klasą podobną do fasoli i implementuje
Serializable
interfejs. Następnie możemy przekazać to przezintent
metodę, na przykład:Następnie pobierz go z innej aktywności, na przykład:
źródło
Utwórz dwie metody w swojej niestandardowej klasie w ten sposób
Teraz u Twojego nadawcy Aktywność tak się robi
I w aktywności odbiornika
źródło
Tak, użycie obiektu statycznego jest zdecydowanie najłatwiejszym sposobem na zrobienie tego z niestandardowymi obiektami nieserializowalnymi.
źródło
static
jest lepszym obejściem, jeśli po prostu niepraktyczne jest wywoływanieputExtra()
każdej właściwości, którą chcesz przekazać. Na przykład teraz chcę przekazać obiektArrayList
zawierający obiekty.static
Zamiast tego równie dobrze mogę utworzyć moją ArrayList .Obiekty aktywności systemu Android można zniszczyć i odtworzyć. Będziesz musiał użyć innego podejścia, aby je wyświetlić - lub dowolnego obiektu, który stworzą !!! - w górę. Oznacza to, że można przekazać jako odwołanie do klasy statycznej, ale wówczas uchwyt obiektu (Java nazywa te „odniesienia”, podobnie jak SmallTalk; ale nie są to odniesienia w znaczeniu C lub zestawu), prawdopodobnie później będzie nieprawidłowy, ponieważ „funkcja” Androida OE to dowolne działanie, które może zostać później unicestwione i odtworzone.
Pierwotne pytanie brzmiało „Jak przekazać obiekt z jednej czynności do drugiej w Androidzie” i nikt na to nie odpowiedział. Na pewno można dokonać serializacji (Serializable, Parcelable, do / z JSON) i przekazać kopię danych obiektu, a nowy obiekt posiadający te same dane mógłby zostać utworzony; ale NIE będzie miał takich samych referencji / uchwytów. Ponadto wiele innych wspomniało, że możesz przechowywać referencje w magazynie statycznym. I to zadziała, chyba że Android zdecyduje się zniszczyć Twoją aktywność.
Tak więc, aby naprawdę rozwiązać pierwotne pytanie, potrzebujesz statycznego wyszukiwania, a każdy obiekt zaktualizuje swoje odwołanie, gdy / jeśli zostanie odtworzony. Np. Każda aktywność Androida pojawiłaby się ponownie, gdyby wywołano jego funkcję onCreate. Możesz także zobaczyć, w jaki sposób niektóre osoby używają listy zadań do wyszukiwania działania według nazwy. (system tymczasowo niszczy to wystąpienie działania, aby zaoszczędzić miejsce..getRunningTasks, lista zadań jest w rzeczywistości wyspecjalizowaną listą najnowszej instancji obiektu dla każdego działania).
Na przykład:
Tak więc szyna komunikatów jest praktycznym rozwiązaniem. Zasadniczo „wykopuje się”. Zamiast starać się mieć odniesienia do obiektów; następnie ponownie zaprojektujesz swój projekt, aby używał MessagePassing zamiast SequentialCode. Wykładniczo trudniejszy do debugowania; ale pozwala zignorować tego rodzaju zrozumienie dotyczące środowiska operacyjnego. W efekcie dostęp do każdej metody obiektu jest odwrócony, więc wywołujący publikuje komunikat, a sam obiekt definiuje moduł obsługi dla tej wiadomości. Dużo więcej kodu, ale może uczynić go solidnym z ograniczeniami OE dla Androida.
Jeśli wszystko, czego chcesz, to najwyższa aktywność (typowa rzecz w aplikacjach na Androida, ponieważ wszędzie potrzebny jest „kontekst”), możesz po prostu umieścić każdą aktywność jako „górną” w statycznej globalnej przestrzeni za każdym razem, gdy wywoływana jest jego funkcja onResume. Wtedy Twój AlertDialog lub cokolwiek, co potrzebuje kontekstu, może po prostu pobrać go stamtąd. Również trochę globalne jest używanie globalne, ale może uprościć przekazywanie kontekstu w górę i w dół wszędzie, a na pewno, gdy używasz MessageBus, to IT JEST globalny.
źródło
Wiem, że ładunek elektrostatyczny jest zły, ale wydaje się, że jesteśmy zmuszeni go tutaj użyć. Problem z parceable / seriazables polega na tym, że dwie czynności mają zduplikowane instancje tego samego obiektu = marnowanie pamięci i procesora.
Aktywność wywoływania
Wywoływane działanie (zwróć uwagę, że onCreate () i onResume () mogą być wywoływane wiele razy, gdy system niszczy i odtwarza działania)
Innym sposobem jest zadeklarowanie pola statycznego klasy, które chcesz przekazać w tej właśnie klasie. Będzie służyć tylko do tego celu. Nie zapominaj, że może on być pusty w onCreate, ponieważ pakiet aplikacji został zwolniony z pamięci przez system i ponownie załadowany później.
Pamiętając o tym, że nadal musisz zarządzać cyklem życia aktywności, możesz zapisać wszystkie dane prosto do wspólnych preferencji, co jest bolesne przy złożonych strukturach danych.
źródło
Powyższe odpowiedzi prawie wszystkie są poprawne, ale dla tych, którzy nie rozumieją tych odpowiedzi Android ma potężną klasę Intencja za jego pomocą dzielisz dane między nie tylko aktywnością, ale innymi składnikami Androida (odbiornik nadawcy, usługi dla treści pod warunkiem, że używamy klasy ContetnResolver bez intencji ). W swojej działalności budujesz intencje
W swojej działalności przyjmującej masz
Musisz wdrożyć interfejs Parceable lub Serializable na swoim obiekcie, aby dzielić się między działaniami. Trudno jest wdrożyć Parcealbe zamiast Serializowalnego interfejsu na obiekcie, dlatego Android ma specjalnie do tego wtyczkę. Pobierz i użyj
źródło
Zawsze zastanawiałem się, dlaczego nie może to być tak proste, jak przywołanie metody innej czynności. Niedawno napisałem bibliotekę narzędzi, która sprawia, że jest prawie tak prosta. Możesz to sprawdzić tutaj ( https://github.com/noxiouswinter/gnlib_android/wiki/gnlauncher ).
GNLauncher sprawia, że wysyłanie obiektów / danych do działania z innego działania itp. Jest tak proste, jak wywoływanie funkcji w działaniu z wymaganymi danymi jako parametrami. Wprowadza bezpieczeństwo typu i eliminuje wszystkie problemy związane z serializacją, dołączaniem się do intencji za pomocą kluczy łańcuchowych i cofaniem tego samego na drugim końcu.
Stosowanie
Zdefiniuj interfejs za pomocą metod, które chcesz wywołać w celu uruchomienia działania.
Zaimplementuj powyższy interfejs działania, aby uruchomić. Powiadom także GNLauncher, kiedy działanie jest gotowe.
W drugim działaniu uzyskaj proxy do powyższego działania i wywołaj dowolną metodę z pożądanymi parametrami.
Zostanie uruchomione pierwsze działanie i zostanie wywołana metoda z wymaganymi parametrami.
Wymagania wstępne
Informacje na temat dodawania zależności można znaleźć na stronie https://github.com/noxiouswinter/gnlib_android/wiki#prerequisites .
źródło
Przekaż obiekt z jednej aktywności do innej.
(1) aktywność źródłowa
(2) docelowa aktywność
źródło
Kiedyś ustawiałem obiekt za pomocą Pacelable lub Serializable do transferu, ale ilekroć dodam inne zmienne do obiektu (modelu), muszę to wszystko zarejestrować. To takie niewygodne.
Przenoszenie obiektu między czynnościami lub fragmentami jest bardzo łatwe.
Android DataCache
źródło
Możemy przekazać obiekt z jednej aktywności do innej:
Wewnątrz
poSuppliersDetails
mamy pewne wartości. Teraz wysyłam ten obiekt do działania docelowego:Jak uzyskać to w ACtivityTwo:
źródło
Przekaż jedno działanie do drugiego:
Uzyskaj wartości:
źródło
Witam wszystkich, widzę wiele dobrych opcji, ale zastanawiałem się, dlaczego nie zastosowano Binding?
Utworzenie spoiwa jest dość proste ...
A stworzenie działki do użycia nie jest wcale takie złe.
Ta logika jest naprawdę fajna, ponieważ faktycznie przekazujesz referencję z działania do działania.
i aby to zrealizować, po prostu ...
Wyślij to
Odzyskaj to
Do diabła, ktoś może oszaleć i sprawić, by ten frajer stał się prawdziwym generycznym.
źródło