Як надіслати об’єкт з однієї діяльності Android на інший за допомогою програми Intents?


849

Як я можу передати об’єкт користувальницького типу з однієї діяльності до іншої за допомогою putExtra()методу класу Намір ?


@UMMA - вам не потрібно продовжувати позначати свої питання "спільнотою Wiki". Подивіться тут: meta.stackexchange.com/questions/11740/…
Дейв Вебб

1
@Paresh: посилання, яке ви надали, порушено. Ви можете запропонувати альтернативу PLZ?
антиплекс


Перевірте цю відповідь. stackoverflow.com/questions/8857546/…
Heitor Colangelo

Я знайшов простий і елегантний метод stackoverflow.com/a/37774966/6456129
Yessy

Відповіді:


751

Якщо ви просто передаєте об'єкти навколо, тоді Parcelable був розроблений для цього. Для використання потрібно трохи більше зусиль, ніж використання вродженої серіалізації Java, але це швидше (і я маю на увазі спосіб, ШЛИШЕ швидше).

Простий приклад того, як реалізувати документи, є:

// simple class that just has one member property as an example
public class MyParcelable implements Parcelable {
    private int mData;

    /* everything below here is for implementing Parcelable */

    // 99.9% of the time you can just ignore this
    @Override
    public int describeContents() {
        return 0;
    }

    // write your object's data to the passed-in Parcel
    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(mData);
    }

    // this is used to regenerate your object. All Parcelables must have a CREATOR that implements these two methods
    public static final Parcelable.Creator<MyParcelable> CREATOR = new Parcelable.Creator<MyParcelable>() {
        public MyParcelable createFromParcel(Parcel in) {
            return new MyParcelable(in);
        }

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

    // example constructor that takes a Parcel and gives you an object populated with it's values
    private MyParcelable(Parcel in) {
        mData = in.readInt();
    }
}

Зауважте, що у випадку, якщо у вас є кілька полів для отримання певної посилки, ви повинні зробити це в тому ж порядку, в якому ви ввели їх (тобто, у підході FIFO).

Якщо у вас є свої об'єкти реалізувати Parcelableце просто питання здачі їх в ваші наміри з putExtra () :

Intent i = new Intent();
i.putExtra("name_of_extra", myParcelableObject);

Тоді ви можете витягнути їх назад за допомогою getParcelableExtra () :

Intent i = getIntent();
MyParcelable myParcelableObject = (MyParcelable) i.getParcelableExtra("name_of_extra");

Якщо ваш клас об’єктів реалізує Parcelable і Serializable, переконайтеся, що ви перейшли до одного з наступних:

i.putExtra("parcelable_extra", (Parcelable) myParcelableObject);
i.putExtra("serializable_extra", (Serializable) myParcelableObject);

14
Як це було б реалізовано, коли mData є об'єктом (наприклад, JSONObject), а не int?
Peter Ajtai

301
Чому просто не можна передавати об’єкт без усього цього? Ми хочемо передати об’єкт, який вже є в пам’яті.
ceklock

110
@tecnotron його додаткові програми знаходяться в різних процесах і мають окремі адресні простори пам'яті, ви не можете просто надіслати покажчик (посилання) на блок пам'яті у вашому процесі та очікувати, що він буде доступний в іншому процесі.
marcinj

12
Що робити, якщо я не можу зробити клас об'єкта серіалізованим чи парцебельним?
Амель Хосе

11
@ceklock причина цього полягає в наступному: Коли активність відходить і пізніше знищується з пам'яті, а потім, коли користувач відкриває її з меню одержувачів, він повинен створити Діяльність там, де він припинився. Це має бути той самий інтерфейс. Об'єкт в цьому випадку не знаходиться в пам'яті. Але наміри є.
тасоман

194

Вам потрібно буде серіалізувати об’єкт у якомусь рядковому поданні. Одне з можливих рядкових представлень - JSON, і один із найпростіших способів серіалізації до / з JSON в android, якщо ви запитаєте мене, це через Google GSON .

У такому випадку ви просто помістіть рядовий зворотне значення з (new Gson()).toJson(myObject);і отримаєте значення рядка та використовуєте fromJsonдля повернення його назад до вашого об'єкта.

Якщо ваш об’єкт не дуже складний, однак, він може не коштувати накладних витрат, і ви можете замість цього передати окремі значення об'єкта.


19
Я здогадуюсь, тому що відповідь fiXedd вирішує ту саму проблему без використання зовнішніх бібліотек таким чином, який є настільки кращим, що ніколи ні в кого не повинно бути причин звертатися до запропонованого нами рішення (невідомого на той час) блискуче рішення fiXedd)
Девід Хедлунд

5
Я думаю, що це правильно. Крім того, JSON є протоколом, більш підходящим для клієнта / сервера, а не потоком до потоку.
mobibob

16
Не обов'язково погана ідея, особливо. оскільки Gson набагато простіше у використанні, ніж реалізація парцеляції для всіх об'єктів, які ви хочете надіслати.
uvesten

7
як я використовую gson у своєму додатку, це дійсно простий і приємний спосіб!
Ларс

16
Хороша відповідь, хоча повне рішення було б String s = (new Gson().toJson(client));і тодіCli client = new Gson().fromJson(s, Cli.class);
Хоакін Юрчук

155

Ви можете надіслати серіалізаційний об'єкт через наміри

// send where details is object
ClassName details = new ClassName();
Intent i = new Intent(context, EditActivity.class);
i.putExtra("Editing", details);
startActivity(i);


//receive
ClassName model = (ClassName) getIntent().getSerializableExtra("Editing");

And 

Class ClassName implements Serializable {
} 

2
Ви також можете надсилати об'єкти парцеляції через наміри.
tony gil

6
"Серіалізація є надзвичайно повільною на Android. Фактично межа в багатьох випадках марна". дивіться на stackoverflow.com/questions/5550670/…
Серафіма

що, якщо діяльність вже запущена, чи потрібно робити startActivity (i); ? Я можу сказати, чи можу я зробити активність A викликом B , і це повертає дані до активності A ? я розгублений?
Франциско Корралес Моралес

3
@ Ефективність Seraphim має значення, якщо ви серіалізуєте багато об'єктів, але користувач не помітить, якщо серіалізація одного об’єкта займає 1 мс або 10 мс. Якщо додатковий намір вже є, Serializableале його немає Parcelable, то рідко варто домагатися цього Parcelable.
Кевін Крумвієде

67

У ситуаціях, коли ви знаєте, що будете передавати дані в програмі, використовуйте "глобалі" (наприклад, статичні класи)

Ось що з цього приводу сказала Діанна Хакборн (хакбод - програмний інженер Google Android):

У ситуаціях, коли ви знаєте, що діяльність проводиться в одному процесі, ви можете просто обмінюватися даними через глобальні точки. Наприклад, у вас може бути глобальний, HashMap<String, WeakReference<MyInterpreterState>> і коли ви створюєте новий MyInterpreterState, придумайте унікальне ім'я для цього і помістіть його в хеш-карту; щоб переслати цей стан до іншої діяльності, просто введіть унікальне ім'я на хеш-карту, і коли буде запущена друга активність, вона може отримати MyInterpreterState з хеш-карти з іменем, яке вона отримує.


25
так, мені здається дивним, що ми отримуємо ці Ці наміри для використання, і тоді топ-інженер каже нам просто використовувати глобальні дані для наших даних. Але там прямо з вуст коней.
Річард Ле Месюр'є,

1
Невже слабка рецензія не стане жертвою вивезення сміття?
uLYsseus

1
@uLYsseus вважає, що це ідея, як тільки ви закінчите з ними в діяльності ... тож, коли відповідна діяльність буде знищена, це дозволить їй gc
Peter Ajtai

1
@RichardLeMesurier Я думав про те ж саме, але потім я заглянув у вищезгадану публікацію Google Групи від Діанні Хакборн, і вона згадує, що справді єдиною проблемою з глобалізаторами буде проблема використання неявних намірів (яка може запустити діяльність поза вашим пакетом ). Це має сенс, як згадує Діанна, тому що ці дії, швидше за все, матимуть нульові знання про користувацькі типи, які ви їм передаєте. Після того, як я прочитав це, мені стало зрозуміліше, чому глобалісти не можуть бути таким поганим маршрутом за обставин, і я подумав, що поділюсь у випадку, якщо й іншим буде цікаво
BMB

наміри були переосмислені до того моменту, коли наміри можна було передати на інший комп'ютер. що, очевидно, не є гарним способом зробити що-небудь, коли у вас фактично є лише один процес, який ви обмінюєте. останній особливо зробив вибір дизайну із намірами, що викликає заплутаність у задніх планах. Є люди, які наполягають на тому, що вони гарна ідея, як правило, тому, що "Google сказав так".
Лассі Кіннунен

49

Ваш клас повинен реалізувати Serializable або Parcelable.

public class MY_CLASS implements Serializable

Після завершення ви можете відправити об'єкт на putExtra

intent.putExtra("KEY", MY_CLASS_instance);

startActivity(intent);

Щоб отримати додаткові послуги, вам потрібно лише зробити

Intent intent = getIntent();
MY_CLASS class = (MY_CLASS) intent.getExtras().getSerializable("KEY");

Якщо ваш клас реалізує Parcelable, використовуйте наступний

MY_CLASS class = (MY_CLASS) intent.getExtras().getParcelable("KEY");

Я сподіваюся, що це допомагає: D


6
Ваш клас повинен реалізувати Serializableнеправильно. Клас може реалізувати, Parcelableнаприклад.
Марк Плано-Лесей

в чому різниця між Parcelable і Serializable @Kernald? з точки зору часу обробки це повільніше / не найкраща практика чи щось таке?
gumuruh

Хоча Serializableце стандартний інтерфейс Java, Parcelableспецифічний для Android. З точки зору продуктивності Parcelable є більш ефективною: developerphil.com/parcelable-vs-serializable
Marc Plano-Lesay

35

Коротка відповідь на швидку потребу

1. Внесіть свій клас до серіалізаційного.

Якщо у вас є якісь внутрішні класи, не забудьте також застосувати їх до Serializable !!

public class SportsData implements  Serializable
public class Sport implements  Serializable

List<Sport> clickedObj;

2. Поставте свій предмет в Намір

 Intent intent = new Intent(SportsAct.this, SportSubAct.class);
            intent.putExtra("sport", clickedObj);
            startActivity(intent);

3. І отримайте ваш об'єкт в іншому класі активності

Intent intent = getIntent();
    Sport cust = (Sport) intent.getSerializableExtra("sport");

дивіться по цьому посиланню, stackoverflow.com/questions/2139134 / ...
RejoylinLokeshwaran

Це ж можна досягти, застосувавши інтерфейс Parcelable. Інтерфейс, що розширюється, потребує більше часу на реалізацію порівняно з Serializable через розмір коду. Але вона працює швидше, ніж Serializable і використовує менше ресурсів.
Kwnstantinos Nikoloutsos

27

якщо ваш об'єктний клас реалізується Serializable, вам більше нічого не потрібно робити, ви можете передавати об'єкт, який може бути серіалізується.
ось чим я користуюся.


24

здійснити серіалізацію у своєму класі

public class Place implements Serializable{
        private int id;
        private String name;

        public void setId(int id) {
           this.id = id;
        }
        public int getId() {
           return id;
        }
        public String getName() {
           return name;
        }

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

Потім ви можете передавати цей об’єкт у намірі

     Intent intent = new Intent(this, SecondAct.class);
     intent.putExtra("PLACE", Place);
     startActivity(intent);

У другій діяльності ви можете отримати такі дані

     Place place= (Place) getIntent().getSerializableExtra("PLACE");

Але коли дані стануть великими, цей метод буде повільним.


16

Існує кілька способів, за допомогою яких можна отримати доступ до змінних або об’єктів в інших класах або Діяльності.

A. База даних

В. спільні переваги.

C. Об'єктна серіалізація.

D. Клас, який може містити загальні дані, може бути названий як Загальні утиліти, це залежить від вас.

E. Передача даних через інтеграли та інтерфейс для парцеляції.

Це залежить від потреб вашого проекту.

A. База даних

SQLite - це база даних з відкритим кодом, яка вбудована в Android. SQLite підтримує стандартні функції реляційних баз даних, такі як синтаксис SQL, транзакції та підготовлені оператори.

Підручники - http://www.vogella.com/articles/AndroidSQLite/article.html

B. Спільні налаштування

Припустимо, ви хочете зберегти ім'я користувача. Таким чином, тепер буде дві речі Ключове ім'я користувача, Значення Значення.

Як зберігати

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

Використовуючи putString (), putBoolean (), putInt (), putFloat (), putLong (), ви можете зберегти бажаний dtatype.

Як отримати

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

http://developer.android.com/reference/android/content/SharedPreferences.html

C. Серіалізація об'єктів

Сертифікація об'єкта використовується, якщо ми хочемо зберегти стан об'єкта для надсилання його по мережі або ви також можете використовувати його за вашими цілями.

Використовуйте квасолю ява та зберігайте в ній одне з його полів та використовуйте для цього геттери та сетер

JavaBeans - класи Java, які мають властивості. Розгляньте властивості як приватні змінні екземпляра. Оскільки вони приватні, єдиний спосіб отримати доступ до них поза класом - це методи у класі. Методи, що змінюють значення властивості, називаються методами встановлення, а методи, які отримують значення властивості, називаються методами getter.

public class VariableStorage implements Serializable  {

    private String inString ;

    public String getInString() {
        return inString;
    }

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


}

Встановіть змінну у вашому методі пошти за допомогою

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

Потім використовуйте об'єктну серіалізацію для серіалізації цього об'єкта, а в іншому класі десеріалізуйте цей об'єкт.

При серіалізації об'єкт може бути представлений у вигляді послідовності байтів, що включає дані об'єкта, а також інформацію про тип об'єкта та типи даних, що зберігаються в об'єкті.

Після того, як серіалізований об'єкт записаний у файл, він може бути прочитаний з файлу та десеріалізований, тобто інформація про тип і байти, які представляють об'єкт, та його дані, можуть бути використані для відтворення об'єкта в пам'яті.

Якщо ви хочете посібник для цього, перейдіть за цим посиланням

http://javawithswaranga.blogspot.in/2011/08/serialization-in-java.html

Отримайте змінну в інших класах

D. Загальні комунальні послуги

Ви можете створити клас самостійно, який може містити загальні дані, які вам часто потрібні у вашому проекті.

Зразок

public class CommonUtilities {

    public static String className = "CommonUtilities";

}

E. Передача даних через інтенти

Будь ласка, зверніться до цього підручника для цього варіанту передачі даних.

http://shri.blog.kraya.co.uk/2010/04/26/android-parcel-data-to-pass-between-activities-using-parcelable-classes/


Хороший підручник, який ви згадуєте в (E) щодо передачі даних через Інтенти.
ремрік

16

Ви можете використовувати для цього Android BUNDLE.

Створіть пакет зі свого класу, наприклад:

public Bundle toBundle() {
    Bundle b = new Bundle();
    b.putString("SomeKey", "SomeValue");

    return b;
}

Потім передайте цей пакет із INTENT. Тепер ви можете відтворити об’єкт свого класу, передаючи схожий пакет

public CustomClass(Context _context, Bundle b) {
    context = _context;
    classMember = b.getString("SomeKey");
}

Декларуйте це у власному класі та користуйтеся.


1
Переважно перед прямим впровадженням Parcelable, IMHO. Пакет реалізує Parcelable сам по собі, тому ви все одно отримаєте підвищення продуктивності, уникаючи при цьому всіх проблем з його реалізацією. Натомість ви можете використовувати пари «значення-значення» для зберігання та отримання даних, які є більш надійними, ніж покладатися на просте замовлення.
Risadinha

Parcelable мені здається складним, у своїй вищевказаній відповіді я використовую метод toBundle з класу на своєму об'єкті, тому об'єкт перетворюється в bundle, і тоді ми можемо використовувати конструктор для перетворення пакету в об'єкт класу.
om252345

Це рішення є життєздатним лише у тому випадку, якщо ви передаєте один об'єкт через наміри.
THEIT

Як і json, але json - це невелика вага, я думаю.
Девід

Чи буде об’єкт, коли я його отримую, тим самим об’єктом чи копією?
Маркус

15

Дякую за допомогу, що розширюється, але я знайшов ще одне необов’язкове рішення

 public class getsetclass implements Serializable {
        private int dt = 10;
    //pass any object, drwabale 
        public int getDt() {
            return dt;
        }

        public void setDt(int dt) {
            this.dt = dt;
        }
    }

У діяльності перший

getsetclass d = new getsetclass ();
                d.setDt(50);
                LinkedHashMap<String, Object> obj = new LinkedHashMap<String, Object>();
                obj.put("hashmapkey", d);
            Intent inew = new Intent(SgParceLableSampelActivity.this,
                    ActivityNext.class);
            Bundle b = new Bundle();
            b.putSerializable("bundleobj", obj);
            inew.putExtras(b);
            startActivity(inew);

Отримати дані в діяльності 2

 try {  setContentView(R.layout.main);
            Bundle bn = new Bundle();
            bn = getIntent().getExtras();
            HashMap<String, Object> getobj = new HashMap<String, Object>();
            getobj = (HashMap<String, Object>) bn.getSerializable("bundleobj");
            getsetclass  d = (getsetclass) getobj.get("hashmapkey");
        } catch (Exception e) {
            Log.e("Err", e.getMessage());
        }

1
хороша відповідь, але підвищити свої стандарти кодування ... +1, хоча за те, щоб принести Серіалізабельність у змаганнях, проте посилки набагато швидші ...
Аміт

13

Я використовую Gson з його настільки потужним і простим api, щоб пересилати об'єкти між видами діяльності,

Приклад

// This is the object to be sent, can be any object
public class AndroidPacket {

    public String CustomerName;

   //constructor
   public AndroidPacket(String cName){
       CustomerName = cName;
   }   
   // other fields ....


    // You can add those functions as LiveTemplate !
    public String toJson() {
        Gson gson = new Gson();
        return gson.toJson(this);
    }

    public static AndroidPacket fromJson(String json) {
        Gson gson = new Gson();
        return gson.fromJson(json, AndroidPacket.class);
    }
}

2 функції ви додаєте їх до об'єктів, які ви хочете надіслати

Використання

Надіслати об’єкт від A до B

    // Convert the object to string using Gson
    AndroidPacket androidPacket = new AndroidPacket("Ahmad");
    String objAsJson = androidPacket.toJson();

    Intent intent = new Intent(A.this, B.class);
    intent.putExtra("my_obj", objAsJson);
    startActivity(intent);

Прийом В

@Override
protected void onCreate(Bundle savedInstanceState) {        
    Bundle bundle = getIntent().getExtras();
    String objAsJson = bundle.getString("my_obj");
    AndroidPacket androidPacket = AndroidPacket.fromJson(objAsJson);

    // Here you can use your Object
    Log.d("Gson", androidPacket.CustomerName);
}

Я використовую його майже у кожному проекті, який я роблю, і у мене немає проблем з продуктивністю.


Дякую, це врятувало мені години надмірності.
Христо Стоянов

10

Я боровся з тією ж проблемою. Я вирішив це за допомогою статичного класу, зберігаючи будь-які потрібні мені дані в HashMap. Зверху я використовую розширення стандартного класу Activity, де я перекрив методи onCreate onDestroy, щоб зробити транспорт і очищення даних приховано. Необхідно змінити деякі смішні налаштування, наприклад, орієнтація на орієнтацію.

Анотація: Не надання загальних предметів для передачі іншій діяльності - це біль у попі. Це як би стріляти в коліно і сподіватися виграти 100 метрів. "Parcable" не є достатньою заміною. Це змушує мене сміятися ... Я не хочу реалізовувати цей інтерфейс для мого API без технологій, як менше я хочу ввести новий шар ... Як це могло бути, що ми в мобільному програмуванні так далеко від сучасна парадигма ...


9

У вашій першій діяльності:

intent.putExtra("myTag", yourObject);

А у вашому другому:

myCustomObject myObject = (myCustomObject) getIntent().getSerializableExtra("myTag");

Не забудьте зробити власний об’єкт серіалізаційним:

public class myCustomObject implements Serializable {
...
}

Розділення краще, ніж серіалізація! Уникайте використання Serializable у коді Android!
Філіпе Бріто

7

Ще один спосіб зробити це - використовувати Applicationоб’єкт (android.app.Application). Ви визначаєте це у своєму AndroidManifest.xmlфайлі як:

<application
    android:name=".MyApplication"
    ...

Потім ви можете зателефонувати цьому з будь-якої діяльності та зберегти об’єкт у Applicationкласі.

У програмі FirstActivity:

MyObject myObject = new MyObject();
MyApplication app = (MyApplication) getApplication();
app.setMyObject(myObject);

У SecondActivity зробіть:

MyApplication app = (MyApplication) getApplication();
MyObject retrievedObject = app.getMyObject(myObject);

Це зручно, якщо у вас є об'єкти, які мають область застосування програми, тобто вони повинні використовуватися протягом усієї програми. Цей Parcelableметод все-таки кращий, якщо ви хочете чітко контролювати область об’єкта або якщо область обмежена.

Це Intents, однак, уникає використання взагалі. Я не знаю, чи підходять вони вам. Іншим способом, яким я скористався, є отримання intідентифікаторів об'єктів, що надсилаються через наміри, та отримання об'єктів, які я маю на Картах, в Applicationоб'єкті.


1
Це не правильний спосіб робити речі, оскільки об’єкти можуть бути змінними, ваш може працювати, якщо ви говорите про статичний об'єкт протягом життєвого циклу програми, але нам потрібні пасивні об'єкти, які можуть бути створені за допомогою веб-сервісу або так stackoverflow.com / a / 2736612/716865
Muhannad A.Alhariri

Я успішно використовував його з об'єктами, створеними з веб-сервісів, маючи область застосування, Mapде об'єкти зберігаються та отримуються за допомогою ідентифікатора. Єдина реальна проблема такого підходу полягає в тому, що Android через деякий час очищає пам'ять, тому вам доведеться перевіряти наявність нулів у вашому onResume (я думаю, що об'єкти, передані у намірах, зберігаються, але я не впевнений). Крім того, я не вважаю це значно неповноцінним.
Саад Фарук

Це найкраща відповідь. Він показує, як різні види діяльності можуть посилатися на одну і ту ж модель даних. Мені знадобилося далеко, щоб довго це відкрити!
Маркус

6

у вашій моделі класу (Object) реалізуйте Serializable, наприклад:

public class MensajesProveedor implements Serializable {

    private int idProveedor;


    public MensajesProveedor() {
    }

    public int getIdProveedor() {
        return idProveedor;
    }

    public void setIdProveedor(int idProveedor) {
        this.idProveedor = idProveedor;
    }


}

і ваша перша діяльність

MensajeProveedor mp = new MensajeProveedor();
Intent i = new Intent(getApplicationContext(), NewActivity.class);
                i.putExtra("mensajes",mp);
                startActivity(i);

і ваша друга активність (NewActivity)

        MensajesProveedor  mensajes = (MensajesProveedor)getIntent().getExtras().getSerializable("mensajes");

Щасти!!


6
public class SharedBooking implements Parcelable{

    public int account_id;
    public Double betrag;
    public Double betrag_effected;
    public int taxType;
    public int tax;
    public String postingText;

    public SharedBooking() {
        account_id = 0;
        betrag = 0.0;
        betrag_effected = 0.0;
        taxType = 0;
        tax = 0;
        postingText = "";
    }

    public SharedBooking(Parcel in) {
        account_id = in.readInt();
        betrag = in.readDouble();
        betrag_effected = in.readDouble();
        taxType = in.readInt();
        tax = in.readInt();
        postingText = in.readString();
    }

    public int getAccount_id() {
        return account_id;
    }
    public void setAccount_id(int account_id) {
        this.account_id = account_id;
    }
    public Double getBetrag() {
        return betrag;
    }
    public void setBetrag(Double betrag) {
        this.betrag = betrag;
    }
    public Double getBetrag_effected() {
        return betrag_effected;
    }
    public void setBetrag_effected(Double betrag_effected) {
        this.betrag_effected = betrag_effected;
    }
    public int getTaxType() {
        return taxType;
    }
    public void setTaxType(int taxType) {
        this.taxType = taxType;
    }
    public int getTax() {
        return tax;
    }
    public void setTax(int tax) {
        this.tax = tax;
    }
    public String getPostingText() {
        return postingText;
    }
    public void setPostingText(String postingText) {
        this.postingText = postingText;
    }
    public int describeContents() {
        // TODO Auto-generated method stub
        return 0;
    }
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(account_id);
        dest.writeDouble(betrag);
        dest.writeDouble(betrag_effected);
        dest.writeInt(taxType);
        dest.writeInt(tax);
        dest.writeString(postingText);

    }

    public static final Parcelable.Creator<SharedBooking> CREATOR = new Parcelable.Creator<SharedBooking>()
    {
        public SharedBooking createFromParcel(Parcel in)
        {
            return new SharedBooking(in);
        }
        public SharedBooking[] newArray(int size)
        {
            return new SharedBooking[size];
        }
    };

}

Передача даних:

Intent intent = new Intent(getApplicationContext(),YourActivity.class);
Bundle bundle = new Bundle();
i.putParcelableArrayListExtra("data", (ArrayList<? extends Parcelable>) dataList);
intent.putExtras(bundle);
startActivity(intent);

Отримання даних:

Bundle bundle = getIntent().getExtras();
dataList2 = getIntent().getExtras().getParcelableArrayList("data");

5

найпростіше рішення, яке я знайшов - це створити клас зі статичними членами даних із встановниками геттерів.

встановити з однієї діяльності і отримати від іншої діяльності цей об’єкт.

діяльність А

mytestclass.staticfunctionSet("","",""..etc.);

діяльність b

mytestclass obj= mytestclass.staticfunctionGet();

1
або створити серіалізаційний клас, щоб перейти до іншої діяльності все, що ви хочете пройти.
УМАР

9
Тільки пам’ятайте, що не кладіть великі жирні предмети. Термін служби цього об’єкта буде таким самим, як і термін служби програми. І ніколи не зберігайте краєвиди. Цей метод також гарантує витоки пам'яті.
Рено

1
Ця відповідь є корисним, але не кращим рішенням щодо оптимізації пам’яті та ресурсів
Atul Bhardwaj

1
Це порушує принципи OOP шляхом впровадження глобальних змінних. Ви ніколи не знаєте, в якому стані вони перебувають, встановлені вони чи ні, вони використовуються багатьма потоками, і вам доведеться мати справу з цією складністю. Зазвичай це хороший витік пам'яті, оскільки ви навіть не знаєте, коли звільнити ці змінні. Не кажучи про те, що він вводить жорстку пряму сполуку між різними модулями програми.
afrish

2
WTF? Інші два відповіді набагато вищі.
IcyFlame

4

ви можете використовувати putExtra (Serializable ..) та getSerializableExtra () методи для передачі та отримання об'єктів типу вашого класу; вам доведеться відзначити свій клас Serializable і переконатися, що всі змінні вашого члена є також серіалізаційними ...


4

Створіть додаток для Android

Файл >> Новий >> Додаток для Android

Введіть назву проекту: android-pass-object-to-activity

Паккадж: com.hmkcode.android

Залишайте інші вибору за замовчуванням, ідіть далі, поки не досягнете Готового

Перш ніж почати створювати додаток, нам потрібно створити клас POJO "Person", який ми будемо використовувати для передачі об'єкта від однієї діяльності до іншої. Зауважте, що клас реалізує інтерфейс Serializable.

Персона.java

package com.hmkcode.android;
import java.io.Serializable;

public class Person implements Serializable{

    private static final long serialVersionUID = 1L;

    private String name;
    private int age;

        // getters & setters....

    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }   
}

Дві схеми для двох видів діяльності

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">
    <TextView
        android:id="@+id/tvName"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:gravity="center_horizontal"
        android:text="Name" />

    <EditText
        android:id="@+id/etName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"

        android:ems="10" >
        <requestFocus />
    </EditText>
</LinearLayout>

<LinearLayout
     android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">
<TextView
    android:id="@+id/tvAge"
    android:layout_width="100dp"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:gravity="center_horizontal"
    android:text="Age" />
<EditText
    android:id="@+id/etAge"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:ems="10" />
</LinearLayout>

<Button
    android:id="@+id/btnPassObject"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:text="Pass Object to Another Activity" />

</LinearLayout>

activity_another.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
 >

<TextView
    android:id="@+id/tvPerson"
    android:layout_height="wrap_content"
    android:layout_width="fill_parent"
    android:layout_gravity="center"
    android:gravity="center_horizontal"
 />

</LinearLayout>

Два класи занять

1) ActivityMain.java

package com.hmkcode.android;

import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends Activity implements OnClickListener {

Button btnPassObject;
EditText etName, etAge;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    btnPassObject = (Button) findViewById(R.id.btnPassObject);
    etName = (EditText) findViewById(R.id.etName);
    etAge = (EditText) findViewById(R.id.etAge);

    btnPassObject.setOnClickListener(this);
}

@Override
public void onClick(View view) {

    // 1. create an intent pass class name or intnet action name 
    Intent intent = new Intent("com.hmkcode.android.ANOTHER_ACTIVITY");

    // 2. create person object
    Person person = new Person();
    person.setName(etName.getText().toString());
    person.setAge(Integer.parseInt(etAge.getText().toString()));

    // 3. put person in intent data
    intent.putExtra("person", person);

    // 4. start the activity
    startActivity(intent);
}

}

2) AnotherActivity.java

package com.hmkcode.android;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.TextView;

public class AnotherActivity extends Activity {

TextView tvPerson;

@Override
protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_another);

    // 1. get passed intent 
    Intent intent = getIntent();

    // 2. get person object from intent
    Person person = (Person) intent.getSerializableExtra("person");

    // 3. get reference to person textView 
    tvPerson = (TextView) findViewById(R.id.tvPerson);

    // 4. display name & age on textView 
    tvPerson.setText(person.toString());

}
}

4

Використовуючи бібліотеку Gson google, ви можете передати об’єкт в інші дії. Фактично ми перетворимо об’єкт у вигляді рядка json, а після переходу до іншої діяльності ми знову повернемося до об’єкта на зразок цього

Розглянемо такий клас квасолі

 public class Example {
    private int id;
    private String name;

    public Example(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

Нам потрібно передати об’єкт класу Example

Example exampleObject=new Example(1,"hello");
String jsonString = new Gson().toJson(exampleObject);
Intent nextIntent=new Intent(this,NextActivity.class);
nextIntent.putExtra("example",jsonString );
startActivity(nextIntent);

Для читання нам потрібно виконати зворотну операцію в NextActivity

 Example defObject=new Example(-1,null);
    //default value to return when example is not available
    String defValue= new Gson().toJson(defObject);
    String jsonString=getIntent().getExtras().getString("example",defValue);
    //passed example object
    Example exampleObject=new Gson().fromJson(jsonString,Example .class);

Додайте цю залежність у градусах

compile 'com.google.code.gson:gson:2.6.2'


3

Я знаю, що це пізно, але це дуже просто. Все, що ви маєте зробити, нехай ваш клас реалізує подібну функцію Serializable

public class MyClass implements Serializable{

}

тоді ви можете перейти до такого наміру

Intent intent=......
MyClass obje=new MyClass();
intent.putExtra("someStringHere",obje);

Щоб отримати це, ви просто зателефонуйте

MyClass objec=(MyClass)intent.getExtra("theString");

2

Якщо у вас в будь-якому випадку є однотонний клас (сервіс fx), який виступає шлюзом до рівня вашої моделі, це можна вирішити, маючи змінну в цьому класі з геттерами та сетерами для нього.

У діяльності 1:

Intent intent = new Intent(getApplicationContext(), Activity2.class);
service.setSavedOrder(order);
startActivity(intent);

У діяльності 2:

private Service service;
private Order order;

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

    service = Service.getInstance();
    order = service.getSavedOrder();
    service.setSavedOrder(null) //If you don't want to save it for the entire session of the app.
}

На сервісі:

private static Service instance;

private Service()
{
    //Constructor content
}

public static Service getInstance()
{
    if(instance == null)
    {
        instance = new Service();
    }
    return instance;
}
private Order savedOrder;

public Order getSavedOrder()
{
    return savedOrder;
}

public void setSavedOrder(Order order)
{
    this.savedOrder = order;
}

Це рішення не вимагає жодної серіалізації чи іншої "упаковки" об'єкта, про який йде мова. Але це буде вигідно лише в тому випадку, якщо ви все одно користуєтеся такою архітектурою.


Які недоліки такого підходу? Це здається таким логічним і струнким. Я завжди читаю, що ти не повинен цього робити, але ніколи не отримую хорошого пояснення, що може піти не так.
Маркус

Оскільки я не можу більше редагувати свій коментар: чи це не єдине можливе рішення отримати посилання на об’єкт замість копії? Мені потрібно отримати той самий предмет, а не копію!
Маркус

Я думаю, що це дещо відлякує через високу муфту, до якої вона призводить. Але так, наскільки я бачу, такий підхід є найбільш життєздатним, якщо вам потрібен власне об’єкт. Як завжди в програмуванні, ви можете робити все, що завгодно, просто хочете робити це обережно. Це рішення працювало на мене, і я вважаю за краще, оскільки я так чи інакше використовую цю архітектуру.
Кіталда

Насправді я закінчив розширення класу Application і зберігав там свою модель даних. У програмі Intents я передавав лише ідентифікатор об'єктів даних, який міг би бути використаний для отримання вихідного об'єкта з класу Application. Також розширений клас додатків повідомляє про всі об'єкти, які використовують модель даних, якщо вона змінюється за допомогою стандартної концепції слухача. Я знаю, що це підходить лише моєму випадку, коли мені потрібно поділитися модель даних по всій програмі, але для цього випадку її ідеальні, а також не потрібні статичні класи та поля!
Маркус

2

Безумовно найпростіший спосіб IMHO для розподілу об'єктів. Ви просто додаєте тег примітки над об'єктом, який ви хочете зробити розбірним.

Приклад з бібліотеки наведено нижче https://github.com/johncarl81/parceler

@Parcel
public class Example {
    String name;
    int age;

    public Example(){ /*Required empty bean constructor*/ }

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

    public String getName() { return name; }

    public int getAge() { return age; }
}

2

Спочатку впроваджуйте Parcelable у своєму класі. Потім передайте такий предмет.

SendActivity.java

ObjectA obj = new ObjectA();

// Set values etc.

Intent i = new Intent(this, MyActivity.class);
i.putExtra("com.package.ObjectA", obj);

startActivity(i);

ReceiveActivity.java

Bundle b = getIntent().getExtras();
ObjectA obj = b.getParcelable("com.package.ObjectA");

Рядок пакету не потрібен, просто рядок повинен бути однаковим в обох видах діяльності

ДОВІДКА


2

Почніть іншу активність з цієї діяльності, передайте параметри через Об'єкт зв’язку

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

Завантажте іншу діяльність (YourActivity)

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

Це нормально для простого типу даних. Але якщо ви хочете передати складні дані між видами діяльності, вам потрібно спочатку їх серіалізувати.

Тут ми маємо модель працівника

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

    getters...
    setters...
}

Ви можете використовувати Gson lib, наданий google, для серіалізації таких складних даних

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

2

У Колтін

Додайте розширення kotlin у свій build.gradle.

apply plugin: 'kotlin-android-extensions'

android {
    androidExtensions {
        experimental = true
   }
}

Потім створіть свій клас даних таким чином.

@Parcelize
data class Sample(val id: Int, val name: String) : Parcelable

Передайте об’єкт з наміром

val sample = Sample(1,"naveen")

val intent = Intent(context, YourActivity::class.java)
    intent.putExtra("id", sample)
    startActivity(intent)

Отримати об’єкт з наміром

val sample = intent.getParcelableExtra("id")

Це все ще експериментально?
ShadeToD

2

Найпростіший і Java-спосіб - це здійснити серіалізацію у класі pojo / model

Рекомендовано для Android для перегляду продуктивності: зробіть модель продільною


1

Найпростішим було б просто використовувати наступне, де елемент - це рядок:

intent.putextra("selected_item",item)

Для отримання:

String name = data.getStringExtra("selected_item");

3
його тільки для рядка, цілого числа і т. д., але я хочу, щоб об'єкт і використання статичного об'єкта були його єдино можливими.
UMAR
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.