Jak przekazać obiekt z jednej czynności do drugiej na Androidzie


778

Próbuję pracować nad wysłaniem obiektu mojej klasy klienta z jednego Activityi 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 Activitydo drugiego, a następnie wyświetlić dane na drugim Activity.

Jak mogę to osiągnąć?


1
prawdopodobnie powinieneś zmienić przyjętą odpowiedź ze względu na masową opinię.
Rohit Vipin Mathews

Kiedyś ustawiałem obiekt na Pacelable lub Serializable, ale ilekroć dodam inne zmienne, muszę dodać to wszystko do funkcji, aby uzyskać i ustawić na Pacelable lub Serializable. więc stworzyłem DataCache do przesyłania między działaniami i fragmentami. github.com/kimkevin/AndroidDataCache Transfer obiektu jest bardzo łatwy.
kimkevin

Odpowiedzi:


886

Jedną z opcji może być pozwolenie klasie niestandardowej na implementację Serializableinterfejsu, a następnie można przekazać instancje obiektów w zamiar za pomocą putExtra(Serializable..)wariantu Intent#putExtra()metody.

Pseudokod :

//To pass:
intent.putExtra("MyClass", obj);

// To retrieve object in second Activity
getIntent().getSerializableExtra("MyClass");

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:

class MainClass implements Serializable {

    public MainClass() {}

    public static class ChildClass implements Serializable {

        public ChildClass() {}
    }
}

126
@OD: W mojej obronie nigdy nie powiedziałem, że to najlepsza opcja; OP właśnie poprosił o alternatywy i zasugerowałem jedną. W każdym razie dzięki.
Samuh

83
Dlaczego Serializable nie jest dobrą opcją? Jest to dobrze znany interfejs, istnieje duża szansa, że ​​klasy ludzi mogą go już zaimplementować (na przykład ArrayList jest już możliwy do serializacji). Dlaczego warto zmienić obiekty danych, aby dodać dodatkowy kod po prostu w celu przekazania ich z jednej klasy do drugiej? To wygląda na zły projekt. Mogę sobie wyobrazić, że może to mieć pewien wpływ na wydajność na pewnym poziomie, ale sądzę, że w 99% przypadków ludzie przesyłają niewielkie ilości danych i nie obchodzi ich to. Prostsze i przenośne jest czasem lepsze.
Nate

16
@Sander: Czy zatem ta odpowiedź ( stackoverflow.com/questions/2139134/... ) jest błędna? Mówi, że Parcelable jest specjalnie zaprojektowany do tego celu (i znacznie szybciej niż Serializable). Jestem zmieszany.
Slauma,

41
Parcelablemoż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 nich Parcelable? SerializableZamiast tego lepiej byłoby użyć . Po wdrożeniu Parcelablemusisz dodać dużo kodu do klasy i uporządkować pola w bardzo specyficzny sposób; Serializablety nie. Ostatecznie myślę, że sprowadza się to do tego, ile przedmiotów mijasz i co próbujesz zrobić.
BlackHatSamurai

15
Serializableto standardowy interfejs Java. Po prostu zaznaczasz klasę Serializable, implementując interfejs, a Java automatycznie serializuje go w określonych sytuacjach. Parcelablejest 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 Java
Gaurav Arora

311

Zaimplementuj swoją klasę dzięki Serializable. Załóżmy, że to twoja klasa jednostek:

import java.io.Serializable;

@SuppressWarnings("serial") //With this annotation we are going to hide compiler warnings
public class Deneme implements Serializable {

    public Deneme(double id, String name) {
        this.id = id;
        this.name = name;
    }

    public double getId() {
        return id;
    }

    public void setId(double id) {
        this.id = id;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    private double id;
    private String name;
}

Wysyłamy obiekt wywołany denez działania X do działania Y. Gdzieś w aktywności X;

Deneme dene = new Deneme(4,"Mustafa");
Intent i = new Intent(this, Y.class);
i.putExtra("sampleObject", dene);
startActivity(i);

W aktywności Y otrzymujemy obiekt.

Intent i = getIntent();
Deneme dene = (Deneme)i.getSerializableExtra("sampleObject");

Otóż ​​to.


1
To było dla mnie bardzo pomocne. Dzięki ... Ale po otrzymaniu przekazanego obiektu, składnia powinna być [Deneme dene = (Deneme) i.getSerializableExtra ("sampleObject"); ] ... Czy to ???
JibW

1
@ MustafaGüven Ale classCastException: java.lang.Longrobię to. Czy możesz wyjaśnić dlaczego?
Shajeel Afzal

Z moją odpowiedzią nie ma żadnego związku. Otrzymujesz coś zupełnie innego. Czy możesz udostępnić swoje kody?
Mustafa Güven

1
Serializowalny jest zbyt wolny dla dużych POJO. Korzystanie z magistrali jest znacznie lepszym wzorcem.
Steven Mark Ford

1
Dlaczego powinienem mieć prefiks (Serializable)do obiektu?
Alston

123
  • Używanie globalnych zmiennych statycznych nie jest dobrą praktyką inżynierii oprogramowania .
  • Przekształcanie pól obiektu w prymitywne typy danych może być ciężkim zadaniem .
  • Korzystanie z serializacji jest OK, ale nie jest wydajne na platformie Android.
  • Parcelable jest specjalnie zaprojektowany dla Androida i powinieneś go używać. Oto prosty przykład: przekazywanie obiektów niestandardowych między działaniami systemu Android

Za pomocą tej strony możesz wygenerować kod paczki dla swojej klasy .


4
Co jeśli mój obiekt zawiera zagnieżdżoną listę Arraylist?
Dr aNdRO

10
Być może, ale naprawdę należy wziąć `` wydajność '' z odrobiną soli imo. Jeśli dzieje się to za cenę wdrożenia Parcelable, wolałbym, aby moje klasy POJO były niezależne od Androida i używane Serializable.
VH-NZZ

Nie zgadzam się, że powinieneś używać paczki. Prosty wzorzec magistrali jest znacznie wydajniejszy w środowisku wykonawczym i pozwala zaoszczędzić sporo czasu deweloperów.
Steven Mark Ford

15
Według tego testu bitbucket.org/afrishman/androidserializationtest Serializable jest znacznie szybszy niż Parcelable. Przestańcie dzielić ten pięcioletni nonsens na temat paczek.
afrish

7
W jaki sposób globalne zmienne statyczne „nie są dobrą praktyką inżynierii oprogramowania”? Możesz zrobić coś takiego jak singleton cache i / lub siatka danych, a następnie przekazywać identyfikatory lub podobne. Kiedy przekazujesz odniesienia w Javie, i tak używasz globalnych zmiennych statycznych, ponieważ wskazują one na ten sam obiekt.
koniec

111

Użyj gson, aby przekonwertować obiekt na JSON i przekazać go przez zamiar. W nowym działaniu przekonwertuj JSON na obiekt.

W swoim build.gradledodaj to do swoich zależności

implementation 'com.google.code.gson:gson:2.8.4'

W swoim działaniu przekonwertuj obiekt na ciąg json:

Gson gson = new Gson();
String myJson = gson.toJson(vp);
intent.putExtra("myjson", myjson);

W działaniu odbierającym przekonwertuj ciąg json z powrotem na oryginalny obiekt:

Gson gson = new Gson();
YourObject ob = gson.fromJson(getIntent().getStringExtra("myjson"), YourObject.class);

Dla Kotlina jest tak samo

Przekaż dane

val gson = Gson()
val intent = Intent(this, YourActivity::class.java)
intent.putExtra("identifier", gson.toJson(your_object))
startActivity(intent)

Odbierz dane

val gson = Gson()
val yourObject = gson.fromJson<YourObject>(intent.getStringExtra("identifier"), YourObject::class.java)

3
To przesada, gson jest tylko rodzajem serializacji ciągów do json, lepiej jest zaimplementować Serializable lub Paracable.
James Roeiter,

14
Nie ma potrzeby implementowania serializowalnego w każdym obiekcie i każdym projekcie (strata czasu), jeśli można użyć biblioteki (gson), która to obsługuje. A jeśli chodzi o przesadę, tam są telefony dual i quadcore, mogą obsłużyć nawet listę zgodnie z tym pomysłem odpowiedzi.
sagits

4
Poleciłbym również użycie gson, ponieważ gson może również serializować listy arraylists oprócz powyższych.
nurgasemetey

4
To jest świetne! W moim przypadku korzystam z biblioteki, w której obiekty nie implementują serializacji ani paczki. Więc to moja jedyna opcja afaik
Chad Bingham

2
To jest najlepsza opcja. Niektóre klasy są tak proste, że nie trzeba
zbytnio

98

Podczas dzwonienia do działania

Intent intent = new Intent(fromClass.this,toClass.class).putExtra("myCustomerObj",customerObj);

W toClass.java otrzymaj aktywność przez

Customer customerObjInToClass = getIntent().getExtras().getParcelable("myCustomerObj");

Upewnij się, że klasa klienta wdraża paczkę

public class Customer implements Parcelable {

    private String firstName, lastName, address;
    int age;

    /* all your getter and setter methods */

    public Customer(Parcel in ) {
        readFromParcel( in );
    }

    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
        public LeadData createFromParcel(Parcel in ) {
            return new Customer( in );
        }

        public Customer[] newArray(int size) {
            return new Customer[size];
        }
    };


    @Override
    public void writeToParcel(Parcel dest, int flags) {

        dest.writeString(firstName);
        dest.writeString(lastName);
        dest.writeString(address);
        dest.writeInt(age);
    }

    private void readFromParcel(Parcel in ) {

        firstName = in .readString();
        lastName  = in .readString();
        address   = in .readString();
        age       = in .readInt();
    }

Adhavan, mam pytanie. Kiedy tworzysz pierwszą klasę Intent, przekazujesz fromClass.this jako pierwszy argument. Czy istnieje sposób na odzyskanie tego obiektu w klasie aktywności odbierającej?
newman

1
Miliu, fromClass fr = (fromClass) getParent (); czy tego potrzebujesz?
Reklamy

Adhava, faktycznie to zrobiłem, ale fr jest zerowy. Masz pomysł, dlaczego?
newman

miliu, proszę udostępnić ślad wyjątku, abyśmy mogli go zbadać.
Reklamy

Paczka ma mnóstwo niepotrzebnego kodu płyty kotła i jest szczerze mówiąc stratą czasu. Raczej użyj autobusu. Zobacz mój post poniżej.
Steven Mark Ford

89

Z mojego doświadczenia wynikają trzy główne rozwiązania, każde z ich wadami i zaletami:

  1. Wdrażanie paczki

  2. Wdrożenie serializowalne

  3. 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.


4
Link do artykułu jest martwy. Nadal dostępny na webarchive: web.archive.org/web/20160917213123/http://…
OlivierH

Szkoda, że ​​link nie działa :(
Mauker

Problem użycia magistrali zdarzeń polega na tym, że docelowe działanie jest odtwarzane na przykład z powodu rotacji. W takim przypadku działanie docelowe nie ma dostępu do przekazanego obiektu, ponieważ obiekt ten został zużyty z magistrali przez wcześniejsze wywołanie.
JuliuszJ

1
Parcelable jest najszybszy i dzięki temu generatorowi ( parcelabler.com ) możesz wkleić swoją klasę i wygenerować kod za ciebie. Prosty.
ByWaleed

1
@ByWaleed ... Absolutnie się zgadzam, zawsze korzystam z tej strony, robię rzeczy bez żadnych kłopotów. Jednak miałem wiele nieudanych prób, gdy próbuję użyć POJO, który składa się z innego obiektu. Z jakiegoś powodu jego wypakowanie naprawdę nie działa.
Yo Apps,

42

Znalazłem prostą i elegancką metodę:

  • NIE Paczkowany
  • NO Serializowalny
  • BEZ pola statycznego
  • Brak magistrali zdarzeń

Metoda 1

Kod pierwszego działania:

    final Object objSent = new Object();
    final Bundle bundle = new Bundle();
    bundle.putBinder("object_value", new ObjectWrapperForBinder(objSent));
    startActivity(new Intent(this, SecondActivity.class).putExtras(bundle));        
    Log.d(TAG, "original object=" + objSent);

Kod drugiego działania:

    final Object objReceived = ((ObjectWrapperForBinder)getIntent().getExtras().getBinder("object_value")).getData();
    Log.d(TAG, "received object=" + objReceived);

znajdziesz objSenti objReceivedmasz to samo hashCode, 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

public class ObjectWrapperForBinder extends Binder {

    private final Object mData;

    public ObjectWrapperForBinder(Object data) {
        mData = data;
    }

    public Object getData() {
        return mData;
    }
}

Metoda 2

  • dla nadawcy
    1. użyj niestandardowej metody rodzimej, aby dodać obiekt Java do globalnej tabeli referencyjnej JNI (za pośrednictwem JNIEnv :: NewGlobalRef)
    2. umieść zwracaną liczbę całkowitą (faktycznie, JNIEnv :: NewGlobalRef return jobject, który jest wskaźnikiem, możemy rzucić go bezpiecznie na int) do twojej intencji (poprzez Intent :: putExtra)
  • dla odbiornika
    1. pobierz liczbę całkowitą z Intent (przez Intent :: getInt)
    2. użyj niestandardowej metody rodzimej, aby przywrócić obiekt Java z globalnej tabeli referencyjnej JNI (przez JNIEnv :: NewLocalRef)
    3. usuń element z globalnej tabeli referencyjnej JNI (przez JNIEnv :: DeleteGlobalRef),

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

package com.example.objectwrapper;
interface IDataContract {
    int func1(String arg1);
    int func2(String arg1);
}

Kod pierwszej aktywności

    final IDataContract objSent = new IDataContract.Stub() {

        @Override
        public int func2(String arg1) throws RemoteException {
            // TODO Auto-generated method stub
            Log.d(TAG, "func2:: arg1=" + arg1);
            return 102;
        }

        @Override
        public int func1(String arg1) throws RemoteException {
            // TODO Auto-generated method stub
            Log.d(TAG, "func1:: arg1=" + arg1);
            return 101;
        }
    };
    final Bundle bundle = new Bundle();
    bundle.putBinder("object_value", objSent.asBinder());
    startActivity(new Intent(this, SecondActivity.class).putExtras(bundle));
    Log.d(TAG, "original object=" + objSent);

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

    final IDataContract objReceived = IDataContract.Stub.asInterface(getIntent().getExtras().getBinder("object_value"));
    try {
        Log.d(TAG, "received object=" + objReceived + ", func1()=" + objReceived.func1("test1") + ", func2()=" + objReceived.func2("test2"));
    } catch (RemoteException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

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

public class MainActivity extends Activity {
    private static final String TAG = "MainActivity";

    public static final int MSG_OP1 = 1;
    public static final int MSG_OP2 = 2;

    public static final String EXTRA_MESSENGER = "messenger";

    private final Handler mHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            // TODO Auto-generated method stub
            Log.e(TAG, "handleMessage:: msg=" + msg);
            switch (msg.what) {
            case MSG_OP1:

                break;
            case MSG_OP2:
                break;

            default:

                break;
            }
            super.handleMessage(msg);
        }

    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        startActivity(new Intent(this, SecondActivity.class).putExtra(EXTRA_MESSENGER, new Messenger(mHandler)));
    }
}

Kod drugiej czynności (odbiorcy):

public class SecondActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);

        final Messenger messenger = getIntent().getParcelableExtra(MainActivity.EXTRA_MESSENGER);
        try {
            messenger.send(Message.obtain(null, MainActivity.MSG_OP1, 101, 1001, "10001"));
            messenger.send(Message.obtain(null, MainActivity.MSG_OP2, 102, 1002, "10002"));
        } catch (RemoteException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

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

package android.os;

import android.os.Message;

/** @hide */
oneway interface IMessenger {
    void send(in Message msg);
}

Przykro mi, ale nie widziałem, że masz również wiążącą odpowiedź. Czuję, że twoja odpowiedź jest również bardzo elegancka.
SkidRunner,

Wow .... Pierwsza metoda tego człowieka jest niesamowita ..... Kiedy masz bardzo duże / większe przedmioty, które działają dobrze
karan

Używam metody pierwszej, więc oszczędzasz mój czas. dzięki;
ShweLiam,

Bardzo dziękuję za metodę ObjectWrapperForBinder, naprawdę pomaga!
Vladimir Tolstikov,

40

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.

String fName_temp   = yourObject.getFname();
String lName_temp   = yourObject.getLname();
String age_temp     = yourObject.getAge();
String address_temp = yourObject.getAddress();

Intent i = new Intent(this, ToClass.class);
i.putExtra("fname", fName_temp);
i.putExtra("lname", lName_temp);
i.putExtra("age", age_temp);
i.putExtra("address", address_temp);

startActivity(i);

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:

String fName = getIntent().getExtras().getInt("fname");

9
odzyskaj swoje dane ponownie za pomocą: String fName = getIntent (). getExtras (). getInt ("fname");
Alister

2
Aby odzyskać dane: Bundle extras = getIntent().getExtras(); String val = extras.getString("fname");
Eric Leschinski

1
Może to szybko stać się niemożliwe dla dużych POJO. Raczej użyj autobusu. Zobacz mój post poniżej.
Steven Mark Ford

jak wspomniałem w mojej odpowiedzi, jest to proste przypadki użycia, w których sam obiekt nie jest potrzebny, a jedynie niektóre jego wartości. To nie jest pomysł na skomplikowane przypadki użycia.
MJB,

1
Dobry pomysł na przekazanie jednego obiektu, ale próbuję przekazać tablicę o nieznanym rozmiarze mojego obiektu. Być może twoim rozwiązaniem nie jest przekazywanie tablic obiektów.
Muhammad Saqib

25

Zrobiłem singletona klasę pomocniczą, która przechowuje przedmioty tymczasowe.

public class IntentHelper {

    private static IntentHelper _instance;
    private Hashtable<String, Object> _hash;

    private IntentHelper() {
        _hash = new Hashtable<String, Object>();
    }

    private static IntentHelper getInstance() {
        if(_instance==null) {
            _instance = new IntentHelper();
        }
        return _instance;
    }

    public static void addObjectForKey(Object object, String key) {
        getInstance()._hash.put(key, object);
    }

    public static Object getObjectForKey(String key) {
        IntentHelper helper = getInstance();
        Object data = helper._hash.get(key);
        helper._hash.remove(key);
        helper = null;
        return data;
    }
}

Zamiast umieszczać obiekty w obszarze Intent, użyj IntentHelper:

IntentHelper.addObjectForKey(obj, "key");

Wewnątrz nowej aktywności możesz uzyskać obiekt:

Object obj = (Object) IntentHelper.getObjectForKey("key");

Pamiętaj, że po załadowaniu obiekt jest usuwany, aby uniknąć niepotrzebnych odniesień.


1
Dobry pomysł! Dodatkowo może być możliwe utworzenie dodatkowej klasy ObjectContainer {Object, obj; boolean permanent; ....} Pomysł polega na tym, że możesz przekazać boolean metodą add, jeśli chcesz zachować trwały obiekt i nie usuwać go, gdy wywołamy get. Pomoże to utrzymać niektóre globalne obiekty. Może to być otwarte połączenie Bluetooth itp.
Umair,

1
Urocze, ale nie wymyślaj na nowo koła. Wzór autobusu jest elegancki i mocniejszy. Zobacz mój post poniżej.
Steven Mark Ford

@StevenMarkFord, więc czy wzór magistrali nadal obowiązuje do dziś? Usiłuję ulepszyć bazę kodu o takim kodzie, jak dostęp do danych między działaniami: BookActivity.getInstance().recommendationResponseinRoomsActivity
Woppi,

Po odtworzeniu działania odbierającego (np. Obracanie ekranu) objstaje się null. Aby tego uniknąć, objnależy go gdzieś przechowywać, aby uzyskać go ponownie. Rzeczywiście, rozwiązanie Json przechowuje dane obiektu w Intent.
Salvador,

25

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ć

 // Create object of SharedPreferences.
 SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);

 //Now get Editor
 SharedPreferences.Editor editor = sharedPref.edit();

 //Put your value
 editor.putString("userName", "stackoverlow");

 //Commits your edits
 editor.commit();

Używając putString (), putBoolean (), putInt (), putFloat () i putLong () możesz zapisać żądany typ danych.

Jak pobrać

SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
String userName = sharedPref.getString("userName", "Not Available");

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.

public class VariableStorage implements Serializable  {

    private String inString;

    public String getInString() {
        return inString;
    }

    public void setInString(String inString) {
        this.inString = inString;
    }
}

Ustaw zmienną w metodzie poczty za pomocą

VariableStorage variableStorage = new VariableStorage();
variableStorage.setInString(inString);

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:

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

public class CommonUtilities {

    public static String className = "CommonUtilities";

}

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 .


22

Utwórz własną klasę Customerw następujący sposób:

import import java.io.Serializable;
public class Customer implements Serializable
{
    private String name;
    private String city;

    public Customer()
    {

    }
    public Customer(String name, String city)
    {
        this.name= name;
        this.city=city;
    }
    public String getName() 
    {
        return name;
    }
    public void setName(String name) 
    {
        this.name = name;
    }
    public String getCity() 
    {
        return city;
    }
    public void setCity(String city) 
    {
        this.city= city;
    }

}

W twojej onCreate()metodzie

@Override
protected void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_top);

    Customer cust=new Customer();
    cust.setName("abc");
    cust.setCity("xyz");

    Intent intent=new Intent(abc.this,xyz.class);
    intent.putExtra("bundle",cust);
    startActivity(intent); 
}

Na xyz activityzajęciach musisz użyć następującego kodu:

Intent intent=getIntent();
Customer cust=(Customer)intent.getSerializableExtra("bundle");
textViewName.setText(cust.getName());
textViewCity.setText(cust.getCity());

..Sprawdź kod, który przekazujesz „pakiet” jako klucz do umieszczenia cust obj i uzyskiwanie z „klasy” ..pls użyj jednego klucza albo „klasy”, albo „pakietu” ..
AK Joshi

Wystąpił błąd: działka napotkała wyjątek IOException podczas pisania obiektu
możliwego do

15

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:

Control.Customer = CustomerClass;

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.


4
@aez Ponieważ jest niechlujny z punktu widzenia projektu i przerwie się okropnie, jeśli zamiar będzie kiedykolwiek w innym procesie.

7
Podczas wznawiania aplikacji do działania B wystąpią problemy, ponieważ działanie może zostać zabite przez system Android, a obiekt nie zostanie zapisany.
Ryan R

15
public class MyClass implements Serializable{
    Here is your instance variable
}

Teraz chcesz przekazać obiekt tej klasy w startActivity. Po prostu użyj tego:

Bundle b = new Bundle();
b.putSerializable("name", myClassObject);
intent.putExtras(b);

Działa to tutaj, ponieważ implementuje MyClass Serializable.


czy możesz wyjaśnić lub rozwinąć więcej
Amitsharma,

HomeworkData homeworkData = homeWorksList.get (position); Intent intent = new Intent (c, HomeWorkActivitydetail.class); Pakiet b = nowy pakiet (); b.putSerializable („CompleteData”, homeworkData); intent.putExtras (b); c.startActivity (intent); w momencie dodawania obiektu pojawia się błąd w dodawaniu elementów obiektu, czy nie możemy przekazać z tym kompletnego obiektu
Amitsharma 30.09.16 o

w pracy domowej Dane mam pewne wartości, które należy dodać
Amitsharma 30.09.16

12

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, i String 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.


8

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.

public class Channel implements Serializable, Parcelable {

    /**  */
    private static final long serialVersionUID = 4861597073026532544L;

    private String cid;
    private String uniqueID;
    private String name;
    private String logo;
    private String thumb;


    /**
     * @return The cid
     */
    public String getCid() {
        return cid;
    }

    /**
     * @param cid
     *     The cid to set
     */
    public void setCid(String cid) {
        this.cid = cid;
    }

    /**
     * @return The uniqueID
     */
    public String getUniqueID() {
        return uniqueID;
    }

    /**
     * @param uniqueID
     *     The uniqueID to set
     */
    public void setUniqueID(String uniqueID) {
        this.uniqueID = uniqueID;
    }

    /**
     * @return The name
     */
    public String getName() {
        return name;
    }

    /**
     * @param name
     *            The name to set
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * @return the logo
     */
    public String getLogo() {
        return logo;
    }

    /**
     * @param logo
     *     The logo to set
     */
    public void setLogo(String logo) {
        this.logo = logo;
    }

    /**
     * @return the thumb
     */
    public String getThumb() {
        return thumb;
    }

    /**
     * @param thumb
     *     The thumb to set
     */
    public void setThumb(String thumb) {
        this.thumb = thumb;
    }


    public Channel(Parcel in) {
        super();
        readFromParcel(in);
    }

    public static final Parcelable.Creator<Channel> CREATOR = new Parcelable.Creator<Channel>() {
        public Channel createFromParcel(Parcel in) {
            return new Channel(in);
        }

        public Channel[] newArray(int size) {

            return new Channel[size];
        }
    };

    public void readFromParcel(Parcel in) {
        String[] result = new String[5];
        in.readStringArray(result);

        this.cid = result[0];
        this.uniqueID = result[1];
        this.name = result[2];
        this.logo = result[3];
        this.thumb = result[4];
    }

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel dest, int flags) {

        dest.writeStringArray(new String[] { this.cid, this.uniqueID,
                this.name, this.logo, this.thumb});
    }
}

W działaniu A użyj go w następujący sposób:

Bundle bundle = new Bundle();
bundle.putParcelableArrayList("channel",(ArrayList<Channel>) channels);
Intent intent = new Intent(ActivityA.this,ActivityB.class);
intent.putExtras(bundle);
startActivity(intent);

W ActivityB użyj go w ten sposób, aby uzyskać dane:

Bundle getBundle = this.getIntent().getExtras();
List<Channel> channelsList = getBundle.getParcelableArrayList("channel");

7

Możesz spróbować użyć tej klasy. Ograniczeniem jest to, że nie można go używać poza jednym procesem.

Jedna aktywność:

 final Object obj1 = new Object();
 final Intent in = new Intent();
 in.putExtra(EXTRA_TEST, new Sharable(obj1));

Inna działalność:

final Sharable s = in.getExtras().getParcelable(EXTRA_TEST);
final Object obj2 = s.obj();

public final class Sharable implements Parcelable {

    private Object mObject;

    public static final Parcelable.Creator < Sharable > CREATOR = new Parcelable.Creator < Sharable > () {
        public Sharable createFromParcel(Parcel in ) {
            return new Sharable( in );
        }


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

    public Sharable(final Object obj) {
        mObject = obj;
    }

    public Sharable(Parcel in ) {
        readFromParcel( in );
    }

    Object obj() {
        return mObject;
    }


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


    @Override
    public void writeToParcel(final Parcel out, int flags) {
        final long val = SystemClock.elapsedRealtime();
        out.writeLong(val);
        put(val, mObject);
    }

    private void readFromParcel(final Parcel in ) {
        final long val = in .readLong();
        mObject = get(val);
    }

    /////

    private static final HashMap < Long, Object > sSharableMap = new HashMap < Long, Object > (3);

    synchronized private static void put(long key, final Object obj) {
        sSharableMap.put(key, obj);
    }

    synchronized private static Object get(long key) {
        return sSharableMap.remove(key);
    }
}

6

Rozpocznij inną aktywność od tej aktywności i przekaż parametry przez Obiekt pakietu

Intent intent = new Intent(getBaseContext(), YourActivity.class);
intent.putExtra("USER_NAME", "xyz@gmail.com");
startActivity(intent);

Odzyskaj dane z innego działania (YourActivity)

String s = getIntent().getStringExtra("USER_NAME");

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

class Employee{
    private String empId;
    private int age;
    print Double salary;

    getters...
    setters...
}

Możesz użyć biblioteki Gson lib dostarczonej przez Google do serializacji złożonych danych w ten sposób

String strEmp = new Gson().toJson(emp);
Intent intent = new Intent(getBaseContext(), YourActivity.class);
intent.putExtra("EMP", strEmp);
startActivity(intent);

Bundle bundle = getIntent().getExtras();
String empStr = bundle.getString("EMP");
            Gson gson = new Gson();
            Type type = new TypeToken<Employee>() {
            }.getType();
            Employee selectedEmp = gson.fromJson(empStr, type);

TypeToken <> jest przestarzały. Jaka jest alternatywa?
Ragavendra M

6

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 Bundleobiektu, w którym przechowywane są niezbędne dane Intent.

 Bundle bundle = new Bundle();

 bundle.putSerializable(key1, value1);
 bundle.putSerializable(key2, value2);
 bundle.putSerializable(key3, value3);

 intent.putExtras(bundle);

Aby wyodrębnić wartości:

 Bundle bundle = new Bundle();

 for (String key : bundle.keySet()) {
 value = bundle.getSerializable(key));
 }

Zaletą Serializablejest jego prostota. Jednak powinieneś rozważyć użycie Parcelablemetody, jeśli potrzebujesz wielu danych do przesłania, ponieważ Parcelablejest specjalnie zaprojektowany dla Androida i jest bardziej wydajny niż Serializable. Możesz stworzyć Parcelablezajęcia używając:

  1. narzędzie online - paczkomat
  2. wtyczka do Android Studio - generator kodów kreskowych Android

5

Kreta jest klasą podobną do fasoli i implementuje Serializableinterfejs. Następnie możemy przekazać to przez intentmetodę, na przykład:

intent.putExtra("class", BeanClass);

Następnie pobierz go z innej aktywności, na przykład:

BeanClass cb = intent.getSerializableExtra("class");

5

Utwórz dwie metody w swojej niestandardowej klasie w ten sposób

public class Qabir {

    private int age;
    private String name;

    Qabir(){
    }

    Qabir(int age,String name){
        this.age=age; this.name=name;
    }   

    // method for sending object
    public String toJSON(){
        return "{age:" + age + ",name:\"" +name +"\"}";
    }

    // method for get back original object
    public void initilizeWithJSONString(String jsonString){

        JSONObject json;        
        try {
            json =new JSONObject(jsonString );
            age=json.getInt("age");
            name=json.getString("name");
        } catch (JSONException e) {
            e.printStackTrace();
        } 
    }
}

Teraz u Twojego nadawcy Aktywność tak się robi

Qabir q= new Qabir(22,"KQ");    
Intent in=new Intent(this,SubActivity.class);
in.putExtra("obj", q.toJSON());
startActivity( in);

I w aktywności odbiornika

Qabir q =new Qabir();
q.initilizeWithJSONString(getIntent().getStringExtra("obj"));

3

Tak, użycie obiektu statycznego jest zdecydowanie najłatwiejszym sposobem na zrobienie tego z niestandardowymi obiektami nieserializowalnymi.


Tak, chyba się z tobą zgadzam. Tworzenie tych obiektów staticjest lepszym obejściem, jeśli po prostu niepraktyczne jest wywoływanie putExtra()każdej właściwości, którą chcesz przekazać. Na przykład teraz chcę przekazać obiekt ArrayListzawierający obiekty. staticZamiast tego równie dobrze mogę utworzyć moją ArrayList .
Matthew Quiros

3

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:

Zatrzymane: „Działanie jest całkowicie zasłonięte przez inne działanie (działanie znajduje się teraz w„ tle ”). Zatrzymane działanie jest również nadal żywe ( Obiekt działania jest zachowany w pamięci , zachowuje wszystkie informacje o stanie i członku, ale nie jest dołączony do menedżera okien). Jednak nie jest już widoczny dla użytkownika i może zostać zabity przez system, gdy pamięć jest potrzebna gdzie indziej. ”

onDestroy „system tymczasowo niszczy to wystąpienie działania, aby zaoszczędzić miejsce”.

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.


Otto jest w stanie uruchomić go zewnętrznie w zwykłej starej aplikacji Java. Tak więc, dobre dla programistów i testowania bez konieczności mieszania się z Androidem. Otto ma dużą krzywą uczenia się i większość tego, co rozwiązuje, jest już rozwiązana na Androida (lokalne programy itp.) Lub w normalnych podejściach do aplikacji (możesz napisać znacznie prostszy przegląd globalny niż przegląd globalny Otto, normalne podejścia są znacznie bardziej przystępne do wektorowania / F3 poprzez kod i do przechodzenia przez debugowanie).
TimJowers2

2
  1. 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.

    public class IntentMailBox {
        static Queue<Object> content = new LinkedList<Object>();
    }

Aktywność wywoływania

IntentMailBox.content.add(level);
Intent intent = new Intent(LevelsActivity.this, LevelActivity.class);
startActivity(intent);

Wywoływane działanie (zwróć uwagę, że onCreate () i onResume () mogą być wywoływane wiele razy, gdy system niszczy i odtwarza działania)

if (IntentMailBox.content.size()>0)
    level = (Level) IntentMailBox.content.poll();
else
    // Here you reload what you have saved in onPause()
  1. 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.

  2. 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.


1

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

Intent intent = new Intent(context,SomeActivity.class);
intent.putExtra("key",value);
startActivity(intent);

W swojej działalności przyjmującej masz

public class SomeActivity extends AppCompactActivity {

    public void onCreate(...){
    ...
          SomeObject someObject = getIntent().getExtras().getParceable("key");
    }

}

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


0

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.

public interface IPayload {
    public void sayHello(String name, int age);
}

Zaimplementuj powyższy interfejs działania, aby uruchomić. Powiadom także GNLauncher, kiedy działanie jest gotowe.

public class Activity_1 extends Activity implements IPayload {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //Notify GNLauncher when the Activity is ready. 
        GNLauncher.get().ping(this);
    }

    @Override
    public void sayHello(String name, int age) {
        Log.d("gnlib_test", "Hello " + name + "! \nYour age is: " + age);
    }
}

W drugim działaniu uzyskaj proxy do powyższego działania i wywołaj dowolną metodę z pożądanymi parametrami.

public class Activity_2 extends Activity {
    public void onClick(View v) {
        ((IPayload)GNLauncher.get().getProxy(this, IPayload.class, Activity_1.class)).sayHello(name, age);
    }
}

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 .


0

Przekaż obiekt z jednej aktywności do innej.

(1) aktywność źródłowa

Intent ii = new Intent(examreport_select.this,
                    BarChartActivity.class);

            ii.putExtra("IntentExamResultDetail",
                    (Serializable) your List<ArraList<String>> object here);
            startActivity(ii);

(2) docelowa aktywność

List<ArrayList<String>> aa = (List<ArrayList<String>>) getIntent()
            .getSerializableExtra("IntentExamResultDetail");

0

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


0

Możemy przekazać obiekt z jednej aktywności do innej:

SupplierDetails poSuppliersDetails = new SupplierDetails();

Wewnątrz poSuppliersDetailsmamy pewne wartości. Teraz wysyłam ten obiekt do działania docelowego:

Intent iPODetails = new Intent(ActivityOne.this, ActivityTwo.class);
iPODetails.putExtra("poSuppliersDetails", poSuppliersDetails);

Jak uzyskać to w ACtivityTwo:

private SupplierDetails supplierDetails;
    supplierDetails =(SupplierDetails) getIntent().getSerializableExtra("poSuppliersDetails");

0

Przekaż jedno działanie do drugiego:

startActivity(new Intent(getBaseContext(),GetActivity.class).putExtra("passingkey","passingvalue"));

Uzyskaj wartości:

String myvalue= getIntent().getExtras("passingkey");

-1

Witam wszystkich, widzę wiele dobrych opcji, ale zastanawiałem się, dlaczego nie zastosowano Binding?

Przekazywanie odniesienia do obiektu wydaje mi się po prostu bardziej wydajne niż serializowanie i destylowanie obiektów, ale nie zrobiłem głębokiego nurkowania, aby zobaczyć, czy to właśnie dzieje się za kulisami.

Utworzenie spoiwa jest dość proste ...

public class MyBinder extends Binder {

    private Object myObject;

    public MyBinder(Object object) {
        myObject = object;
    }

    public Object getObject() {
        return myObject;
    }

}

A stworzenie działki do użycia nie jest wcale takie złe.

public class MyParcelable implements Parcelable {

    private Object myObject;

    public MyParcelable() {
    }

    public MyParcelable(Parcel parcel) {
        myObject = ((MyBinder)parcel.readStrongBinder()).getObject();
    }

    public void setObject(Object object) {
        myObject = object;
    }

    public Object getObject() {
        return myObject;
    }

    public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeStrongBinder(new MyBinder(myObject));
    }

    public int describeContents() {
        return myObject == null ? 0 : 1;
    }

    public static final Parcelable.Creator<MyParcelable> CREATOR = new Parcelable.Creator<MyParcelable>() {

        public MyParcelable createFromParcel(Parcel parcel) {
            return new MyParcelable(parcel);
        }

        public MyParcelable[] newArray(int length) {
            return new MyParcelable[length];
        }

    };
}

Ta logika jest naprawdę fajna, ponieważ faktycznie przekazujesz referencję z działania do działania.

Radziłbym sprawdzić wartości zerowe i czy instancja Binder to MyBinder!

i aby to zrealizować, po prostu ...

Wyślij to

Object myObject = "some object";
MyParcelable myParcelable = new MyParcelable();
myParcelable.setObject(myObject);

intent.putExtra("MyParcelable", myParcelable);

Odzyskaj to

myParcelable = (MyParcelable) getIntent().getExtras().getParcelable("MyParcelable");
myObject = myParcelable.getObject();

Do diabła, ktoś może oszaleć i sprawić, by ten frajer stał się prawdziwym generycznym.

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.