Как передать объект из одного действия в другое на Android

Я пытаюсь отправить объект моего класса customer из одного Activity и отобразить его в другом Activity.

Код для класса клиента:

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

Я хочу отправить его объект из одного Activity в другой, а затем отобразить данные на другом Activity.

Как я могу этого добиться?


person kaibuki    schedule 29.04.2010    source источник
comment
Раньше я устанавливал для объекта Pacelable или Serializable, но всякий раз, когда я добавляю другие переменные, мне приходится добавлять все это в функции для получения и установки для Pacelable или Serializable. поэтому я сделал DataCache для передачи между действиями и фрагментами. github.com/kimkevin/AndroidDataCache Перенести объект очень просто.   -  person kimkevin    schedule 04.10.2015
comment
Я создал оболочку TrackedReference ‹Any›, которая может быть разделена на части и сериализована без необходимости маршалинга (сериализации или сортировки) для базового типа: stackoverflow. com / a / 64944753/3405387   -  person Lukas    schedule 21.11.2020
comment
почему бы вам просто не использовать статические переменные и не получить к ним доступ из другой активности, не воссоздавая их в памяти, а также стерилизация объекта может потреблять ресурсы.   -  person nhCoder    schedule 01.12.2020


Ответы (33)


Один из вариантов может заключаться в том, чтобы позволить вашему пользовательскому классу реализовать интерфейс Serializable, а затем вы можете передавать экземпляры объекта в намерении extra, используя вариант putExtra(Serializable..) метода Intent#putExtra().

Псевдокод:

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

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

Примечание. Убедитесь, что в каждом вложенном классе вашего основного настраиваемого класса реализован интерфейс Serializable, чтобы избежать каких-либо исключений сериализации. Например:

class MainClass implements Serializable {

    public MainClass() {}

    public static class ChildClass implements Serializable {

        public ChildClass() {}
    }
}
person Samuh    schedule 29.04.2010
comment
У меня такая же ситуация, когда я реализую Serializable, нужно ли мне делать что-то особенное в моем классе, нужно ли мне реализовывать некоторые методы? - person Pentium10; 27.05.2010
comment
@OD: В свое оправдание я никогда не говорил, что это лучший вариант; OP просто попросил альтернативы, и я предложил один. В любом случае спасибо. - person Samuh; 10.05.2011
comment
Почему Serializable - не лучший вариант? Это хорошо известный интерфейс, есть большая вероятность, что классы людей уже могут его реализовать (например, ArrayList уже является Serializable). Почему вам нужно изменять свои объекты данных, чтобы добавить дополнительный код, просто чтобы передать их из одного класса в другой? Это похоже на плохой дизайн. Я могу представить, что на каком-то уровне может быть какое-то влияние на производительность, но я думаю, что в 99% случаев люди передают небольшие объемы данных, и им все равно. Иногда лучше и проще, и портативнее. - person Nate; 22.08.2011
comment
Я также добавлю, что, поскольку этот вопрос не общий, а конкретный (относительно класса Customer), в этом случае производительность для такого простого крошечного объекта данных должна быть незначительной. - person Nate; 22.08.2011
comment
Напротив, Parcelable не рекомендуется как механизм для передачи объекта между действиями, он предназначен для IPC. Так что сериализуемый - хороший вариант, просто используйте его с умом ... - person Sander Versluys; 13.09.2011
comment
@Sander: Это ответ (stackoverflow.com/questions/2139134/) не так? Он говорит, что Parcelable IS специально разработан для этой цели (и намного быстрее, чем Serializable). Я в замешательстве. - person Slauma; 02.10.2011
comment
@Slauma на самом деле оба работают, но Parcelable изначально был создан для использования в IPC из-за накладных расходов при использовании Serializable. Но для простого переноса объектов между действиями это незаметно, и вся сложность, связанная с использованием Parcelables, не стоит того, IMO. Они не будут включать метод putSerializable в интерфейс Bundles, если его использование не рекомендуется и на сегодняшний день не является устаревшим. Так что, на мой взгляд, когда вы уверены, что IPC вам не нужен, используйте интерфейс Serializable, это намного проще. Избегайте графов больших объектов, но то же самое было бы справедливо и для Parcelable. - person Sander Versluys; 03.10.2011
comment
Я просто хотел бы добавить реальный пример ... Я использовал сериализуемый для передачи сложного объекта между действиями. Создание намерения заняло 200 мс, а его чтение в принимающей активности заняло более 100 мс, после перехода на parcelable оно упало до 6 мс и 68 мс соответственно. Так что однозначно стоит использовать parcelable для скорости - person Steven Elliott; 25.06.2012
comment
Parcelable может быть хорошо для скорости, но его сложно реализовать. Что, если у вас есть 8 объектов, которые вам нужно передавать между действиями, вы собираетесь делать каждый Parcelable? Было бы разумнее использовать вместо этого Serializable. Когда вы реализуете Parcelable, вам нужно добавить в класс много кода и упорядочить поля очень специфическим образом; Serializable не знаешь. В конечном итоге, я думаю, все сводится к тому, сколько объектов вы проходите и что пытаетесь сделать. - person BlackHatSamurai; 14.08.2012
comment
Serializable - стандартный интерфейс Java. Вы просто помечаете класс как Serializable, реализуя интерфейс, и Java автоматически сериализует его в определенных ситуациях. Parcelable - это специальный интерфейс для Android, в котором вы сами реализуете сериализацию. Он был создан, чтобы быть гораздо более эффективным, чем Serializable, и чтобы обойти некоторые проблемы со стандартной схемой сериализации Java. - person Gaurav Arora; 06.12.2012
comment
Если вам интересно, почему не Serializable: проблема с этим подходом в том, что используется отражение, а это медленный процесс. Этот механизм также имеет тенденцию создавать множество временных объектов и вызывать сборку мусора. из developerphil.com/parcelable-vs-serializable - person none; 04.03.2014
comment
Serializable слишком медленный для больших POJO. Использование автобуса - гораздо лучший вариант. - person Steven Mark Ford; 25.07.2014
comment
Почему нельзя просто передать объект как есть? Какой смысл сериализации, а затем десериализации в другом действии? Это не похоже на то, что вы разбираете это между разными языками или машинами? Его от одного класса к другому? - person Zapnologica; 07.10.2014
comment
Я думаю, что принятый ответ здесь достаточен и более рекомендуется с точки зрения производительности по сравнению с Serializable или Parcelable. В Android инкапсуляция не очень важна, а в Android инкапсуляция не рекомендуется из соображений производительности. Просто помните о подводных камнях использования статического значения, которые могут привести к чему-то неожиданному в зависимости от вашего варианта использования. - person gilsaints88; 28.01.2015
comment
Так как же мы можем передать String, которая технически является объектом, но не любым другим типом объекта? iOS обрабатывает эту функцию с помощью единственного назначения переменной, почему в Android есть этот запрещающий метод передачи данных? - person JamEngulfer; 29.04.2016
comment
Проголосовали за, так как в этом ответе рассказывается о методе, рекомендованном Android. Но если сериализуемый (или пакетный) является рекомендуемым решением, то это все равно, что вернуться к написанию кода в 1970-х годах. Концепция OOPS создается вокруг объектов. Если список и подробный экран не могут использовать один и тот же объект, тогда мы можем также написать код в пещерах. Ужасно с Android - person Krishnabhadra; 04.09.2019

Реализуйте свой класс с помощью Serializable. Предположим, что это ваш класс сущности:

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

Мы отправляем объект с именем dene из активности X в активность Y. Где-то в активности X;

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

В Y-действии мы получаем объект.

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

Вот и все.

person Mustafa Güven    schedule 19.10.2011
comment
Это было действительно полезно для меня. Спасибо ... Но при получении переданного объекта синтаксис должен быть [Deneme dene = (Deneme) i.getSerializableExtra (sampleObject); ] ... Это ??? - person JibW; 21.02.2012
comment
@ MustafaGüven Но от этого я получаю classCastException: java.lang.Long. Не могли бы вы объяснить почему? - person Shajeel Afzal; 17.06.2013
comment
К моему ответу никакого отношения не имеет. Вы получаете совсем другое. Не могли бы вы поделиться своими кодами? - person Mustafa Güven; 18.06.2013
comment
Serializable слишком медленный для больших POJO. Использование автобуса - гораздо лучший вариант. - person Steven Mark Ford; 25.07.2014
comment
Почему я должен добавлять к объекту префикс (Serializable)? - person Alston; 24.09.2014
comment
просто. это из-за передачи. вам нужно найти подробное объяснение сериализации и ее цели в java (то же самое в С #) - person Mustafa Güven; 24.09.2014
comment
Просто побочное примечание, AFAIK в Android действительно не рекомендуется инкапсулировать члены класса с помощью сеттеров и геттеров из-за небольших накладных расходов на производительность. Рекомендуется обращаться к ним напрямую. - person gilsaints88; 28.01.2015
comment
предпочитаю, чтобы эта реализация parceable настолько раздражала в использовании, и разница не заметна для небольших объектов - person CommonSenseCode; 29.10.2015

Используйте gson, чтобы преобразовать ваш объект в JSON и передать его через намерение. В новом действии преобразуйте JSON в объект.

В вашем build.gradle добавьте это в свои зависимости

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

В своей деятельности преобразуйте объект в json-строку:

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

В получающем действии преобразуйте json-строку обратно в исходный объект:

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

Для Kotlin то же самое

Передайте данные

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

Получите данные

val gson = Gson()
val yourObject = gson.fromJson<YourObject>(intent.getStringExtra("identifier"), YourObject::class.java)
person khalid    schedule 31.10.2013
comment
Это излишество, gson - это просто тип сериализации строк в json, лучше реализовать Serializable или Paracable. - person James Roeiter; 22.12.2013
comment
Нет необходимости реализовывать сериализуемые в каждом объекте и в каждом проекте (пустая трата времени), если вы можете использовать библиотеку (gson), которая это обрабатывает. Что касается избыточности, есть двухъядерные и четырехъядерные телефоны, они могут справиться даже со списком, следуя этой идее ответа. - person sagits; 22.01.2015
comment
Я также рекомендовал бы использовать gson, потому что gson также может сериализовать массивы в дополнение к вышеупомянутому. - person nurgasemetey; 09.02.2015
comment
Отлично! В моем случае я использую библиотеку, в которой объекты не реализуют сериализуемые или парцеллируемые. Так что это мой единственный вариант афаик - person Chad Bingham; 16.04.2016
comment
У меня проблема с Gson - ›здесь stackoverflow.com/questions/ 39535222 / issues-with-gson-library - person jose920405; 16.09.2016
comment
Это лучший вариант. Некоторые классы настолько просты, что вам не нужно слишком усложнять их реализацию, реализуя сериализуемые - person Ojonugwa Jude Ochalifu; 09.08.2017
comment
ИМХО, думая о опыте разработчика, я придерживаюсь этого решения. Я не против заплатить незначительные затраты на преобразование моего простого pojo в json, сохраняя при этом представляющий класс как можно более простым. - person Jossef Harush; 18.05.2018
comment
Разве gson не медленнее сериализации? - person john ktejik; 08.10.2018
comment
Метод Kotlin - это getString, а не getStringExtra, но он не позволяет мне редактировать ответ, потому что изменения должны содержать не менее 6 символов. - person Randy; 22.05.2019

  • Использование глобальных статических переменных - не лучшая практика разработки программного обеспечения.
  • Преобразование полей объекта в примитивные типы данных может оказаться сложной задачей.
  • Использование сериализации - это нормально, но это не снижает производительность на платформе Android.
  • Parcelable специально разработан для Android, и вам следует его использовать. Вот простой пример: Передача настраиваемых объектов между Действия для Android

Вы можете сгенерировать код Parcelable для своего класса с помощью этого сайта.

person SohailAziz    schedule 16.04.2012
comment
Что, если мой объект содержит вложенный Arraylist? - person Dr. aNdRO; 27.03.2014
comment
Что ж, возможно, но к `` производительности '' действительно стоит относиться с долей скептицизма. Если это происходит за счет реализации Parcelable, я бы предпочел оставить свои классы POJO-независимыми от Android и использовать Serializable. - person VH-NZZ; 13.05.2014
comment
Я не согласен с тем, что вам следует использовать Parcelable. Простой шаблон BUS намного эффективнее во время выполнения и значительно экономит время разработки. - person Steven Mark Ford; 25.07.2014
comment
Согласно этому тесту bitbucket.org/afrishman/androidserializationtest Serializable намного быстрее, чем Parcelable. Пожалуйста, прекратите рассказывать эту 5-летнюю чушь о Parcelable. - person afrish; 29.03.2015
comment
В нынешнем виде этот ответ почти только по ссылке. Можете ли вы добавить пример кода или что-то в этом роде? - person Justin; 19.02.2016
comment
Почему глобальные статические переменные не являются хорошей практикой разработки программного обеспечения? Вы можете создать что-то вроде одноэлементного кеша и / или сетки данных, а затем передать идентификаторы или что-то подобное. Когда вы передаете ссылки в Java, вы в некотором смысле все равно используете глобальные статические переменные, поскольку они указывают на один и тот же объект. - person breakline; 26.02.2016
comment
но при реализации интерфейса Parcelable и получении через Receiver я получаю RuntimeException. - person guru_007; 31.07.2017
comment
@afrish неактивная ссылка, см. архив для результаты: в 3,6 раза быстрее, чем Parcelable для записи и примерно в 1,6 раза быстрее для чтения - person dantechguy; 04.01.2021

При вызове деятельности

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

В toClass.java получите активность от

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

Убедитесь, что класс клиента реализует parcelable

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();
    }
person Ads    schedule 03.08.2011
comment
Адхаван, у меня вопрос. Когда вы создаете первый класс Intent, вы передаете fromClass.this в качестве первого аргумента. Есть ли способ получить этот объект в принимающем классе активности? - person newman; 11.09.2011
comment
Милиу, fromClass fr = (fromClass) getParent (); это то, что тебе нужно? - person Ads; 12.09.2011
comment
Адхава, я действительно это сделал, но fr - ноль. Есть идеи, почему? - person newman; 25.09.2011
comment
miliu, пожалуйста, поделитесь своей трассировкой исключения, чтобы мы могли ее изучить. - person Ads; 26.09.2011
comment
В Parcelable чертовски много ненужного кода котельной плиты, и, честно говоря, это пустая трата времени. Скорее воспользуйтесь автобусом. Смотрите мой пост ниже. - person Steven Mark Ford; 25.07.2014

По моему опыту, есть три основных решения, каждое со своими недостатками и преимуществами:

  1. Реализация Parcelable

  2. Реализация Serializable

  3. Использование какой-либо облегченной библиотеки шины событий (например, EventBus Greenrobot или Otto Square)

Parcelable - быстрый и стандартный для Android, но имеет много шаблонного кода и требует жестко запрограммированных строк для справки при извлечении значений из намерения (не строго типизированный).

Serializable - почти нулевой шаблон, но это самый медленный подход, а также требует жестко запрограммированных строк при извлечении значений из намерения (не строго типизированный).

Event Bus - нулевой шаблон, самый быстрый подход и не требует жестко запрограммированных строк, но требует дополнительной зависимости (хотя обычно она легковесна, ~ 40 КБ)

Я опубликовал очень подробное сравнение этих трех подходов, включая тесты эффективности.

person Steven Mark Ford    schedule 18.11.2013
comment
Ссылка на статью мертва. Все еще доступно в веб-архиве: https://web.archive.org/web/20160917213123/http://www.stevenmarkford.com/passing-objects-between-android-activities - person OlivierH; 01.04.2017
comment
Обидно, что ссылка не работает :( - person Mauker; 28.06.2017
comment
Проблема использования Event Bus заключается в том, что целевая Activity воссоздается, например, из-за вращения. В этом случае целевая Activity не имеет доступа к переданному объекту, потому что этот объект был потреблен из шины предыдущим вызовом. - person JuliuszJ; 06.02.2018
comment
@JuliuszJ, чем это отличается от других вариантов? вам всегда придется сохранять какое-то состояние в целевой активности, когда она изначально его получает, независимо от того, какой подход. Если вам нужно, существует также концепция прикрепленного автобусного сообщения. - person Steven Mark Ford; 09.02.2018
comment
На данный момент я удалил ссылку на свой блог. Пока я не решу восстановить свой блог. - person Steven Mark Ford; 12.06.2018
comment
Parcelable - самый быстрый, и с помощью этого генератора (parcelabler.com) вы можете вставить свой класс, и он может сгенерировать код для вас. Простой. - person ByWaleed; 16.04.2019
comment
@ByWaleed ... Абсолютно согласен, я всегда пользуюсь этим сайтом, делаю вещи без всяких хасселей. Однако у меня было много неудачных попыток, когда я пытался использовать POJO, состоящий из другого объекта. По какой-то причине его выход на самом деле не работает. - person Yo Apps; 19.06.2019
comment
@Yo Apps, я думаю, вам не хватает некоторых мелких деталей, что означает, что это не работает. Посмотрите на ошибки, которые вы получаете, и которые могут привести к тому, где находится проблема. Тем не менее, вы не можете гарантировать 100% совместимость с такой автоматизированной системой, и вам придется использовать свой интеллект программирования для поиска ошибок. Часто они небольшие, но также могут возникать из-за того, что вы не совсем понимаете, чего вы хотите достичь или как использовать доступные инструменты для достижения этого результата. - person ByWaleed; 02.07.2019

Я нашел простой и элегантный метод:

  • НЕТ посылки
  • НЕТ Сериализуемого
  • НЕТ статического поля
  • Без шины событий

Способ 1

Код для первого действия:

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

Код для второго действия:

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

вы обнаружите, что objSent и objReceived имеют одинаковые hashCode, поэтому они идентичны.

Но почему мы можем передавать таким образом объект java?

Фактически, связыватель android создаст глобальную ссылку JNI для объекта java и выпустит эту глобальную ссылку JNI, когда для этого объекта java нет ссылки. binder сохранит эту глобальную ссылку JNI в объекте Binder.

* ВНИМАНИЕ: этот метод работает ТОЛЬКО, если два действия не выполняются в одном процессе, в противном случае выбросить ClassCastException в (ObjectWrapperForBinder) getIntent (). getExtras (). getBinder ("object_value") *

определение класса ObjectWrapperForBinder

public class ObjectWrapperForBinder extends Binder {

    private final Object mData;

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

    public Object getData() {
        return mData;
    }
}

Способ 2

  • for the sender,
    1. use custom native method to add your java object to JNI global reference table(via JNIEnv::NewGlobalRef)
    2. поместите возвращаемое целое число (фактически, JNIEnv :: NewGlobalRef return jobject, который является указателем, мы можем безопасно преобразовать его в int) в ваше намерение (через Intent :: putExtra)
  • for the receiver
    1. get integer from Intent(via Intent::getInt)
    2. используйте собственный собственный метод для восстановления вашего java-объекта из глобальной справочной таблицы JNI (через JNIEnv :: NewLocalRef)
    3. удалить элемент из глобальной справочной таблицы JNI (через JNIEnv :: DeleteGlobalRef),

Но у метода 2 есть небольшая, но серьезная проблема: если получателю не удается восстановить объект java (например, какое-то исключение происходит перед восстановлением объекта java, или действие получателя вообще не существует), то объект java станет сирота или утечка памяти, метод 1 не имеет этой проблемы, потому что связыватель Android будет обрабатывать это исключение

Способ 3

Чтобы вызвать java-объект удаленно, мы создадим контракт / интерфейс данных для описания java-объекта, мы будем использовать вспомогательный файл

IDataContract.aidl

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

Код для первого действия

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

Код для второго действия:

измените атрибут android: process в AndroidManifest.xml на непустое имя процесса, чтобы второе действие выполнялось в другом процессе

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

Таким образом, мы можем передать интерфейс между двумя действиями, даже если они выполняются в разных процессах, и вызвать метод интерфейса удаленно.

Метод 4

метод 3 кажется недостаточно простым, потому что мы должны реализовать вспомогательный интерфейс. Если вы просто хотите выполнить простую задачу, а возвращаемое значение метода не нужно, мы можем использовать android.os.Messenger.

Код для первого действия (отправитель):

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

Код для второго действия (получателя):

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

    }
}

Весь Messenger.send будет выполняться в обработчике асинхронно и последовательно.

Фактически, android.os.Messenger также является вспомогательным интерфейсом, если у вас есть исходный код Android, вы можете найти файл с именем IMessenger.aidl

package android.os;

import android.os.Message;

/** @hide */
oneway interface IMessenger {
    void send(in Message msg);
}
person Yessy    schedule 12.06.2016
comment
Извините, я не заметил, что в вашем ответе есть привязка. Я считаю, что ваш ответ также очень элегантен. - person SkidRunner; 13.07.2016
comment
Вау .... 1-й метод этого человека потрясающий ... Когда у вас есть очень большие / большие объекты, он работает хорошо - person karan; 17.04.2019
comment
Большое спасибо за метод ObjectWrapperForBinder, действительно помогает! - person Vladimir Tolstikov; 10.12.2019
comment
Это действительно отличные методы: легкие и простые. Мне просто нужно было проверить уровень API во время выполнения, поскольку для putBinder нужен уровень 18. Я сделал это с помощью чего-то вроде (android.os.Build.VERSION.SDK_INT ›= Build.VERSION_CODES.JELLY_BEAN_MR2), и он работает как шарм. Я использую метод 1. - person Gauthier; 10.07.2020

Вы также можете записать данные объекта во временные строки и целые числа и передать их действию. Конечно, таким образом вы переносите данные, но не сам объект.

Но если вы просто хотите отобразить их, а не использовать объект в другом методе или что-то в этом роде, этого должно быть достаточно. Я сделал это так же, чтобы просто отобразить данные из одного объекта в другом действии.

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

Вы также можете передать их напрямую, а не temp ivars, но, на мой взгляд, так будет понятнее. Кроме того, вы можете установить временные ivars на null, чтобы они быстрее очищались GarbageCollector.

Удачи!

Замечание: переопределите toString () вместо написания собственного метода печати.

Как упоминается в комментариях ниже, вот как вы возвращаете свои данные в другом действии:

String fName = getIntent().getExtras().getInt("fname");
person MJB    schedule 29.04.2010
comment
верните свои данные снова с помощью: String fName = getIntent (). getExtras (). getInt (fname); - person Alister; 30.10.2010
comment
Чтобы вернуть данные: Bundle extras = getIntent().getExtras(); String val = extras.getString("fname"); - person Eric Leschinski; 01.01.2012
comment
Это может быстро стать невозможным для больших POJO. Скорее воспользуйтесь автобусом. Смотрите мой пост ниже. - person Steven Mark Ford; 25.07.2014
comment
как я уже упоминал в своем ответе, это для простых случаев использования, когда вам не нужен сам объект, а нужны лишь некоторые его значения. Это не значит, что он подходит для сложных сценариев использования. - person MJB; 31.07.2014
comment
Хорошая идея передать один объект, но я пытаюсь передать массив неизвестного размера моего объекта. Возможно, ваше решение не для передачи массивов объектов. - person Muhammad Saqib; 26.08.2015
comment
да, исходный вопрос был задан для передачи одного объекта другому действию, а не массиву. для этого есть более эффективные и лучшие решения. - person MJB; 26.08.2015

Я создал одноэлементный вспомогательный класс, содержащий временные объекты.

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

Вместо того, чтобы помещать свои объекты в Intent, используйте IntentHelper:

IntentHelper.addObjectForKey(obj, "key");

Внутри вашего нового Activity вы можете получить объект:

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

Имейте в виду, что после загрузки объект удаляется, чтобы избежать ненужных ссылок.

person Roger Sanoli    schedule 20.06.2012
comment
Отличная идея! Дополнительно можно создать дополнительный класс ObjectContainer {Object, obj; логическое постоянное; ....} Идея состоит в том, что вы можете передать логическое значение в методе добавления, если вам нужно сохранить объект постоянным и не удалять, когда мы вызываем get. Это поможет сохранить некоторые глобальные объекты. Например, может быть открытое соединение Bluetooth и т. Д. - person Umair; 26.09.2012
comment
Симпатично, но не изобретайте колесо заново. Схема шины элегантна и мощнее. Смотрите мой пост ниже. - person Steven Mark Ford; 25.07.2014
comment
@StevenMarkFord, так остается ли схема автобуса до сих пор? Я пытаюсь улучшить кодовую базу с помощью такого кода для доступа к данным между действиями: BookActivity.getInstance().recommendationResponse в RoomsActivity - person Woppi; 20.12.2017
comment
Когда принимающая активность воссоздается (например, при повороте экрана) obj становится null. Чтобы этого избежать, obj следует где-то хранить, чтобы получить его снова. Действительно, решение Json хранит данные объекта в Intent. - person Salvador; 07.08.2018

Есть несколько способов получить доступ к переменным или объектам в других классах или Activity.

A. База данных

Б. Общие предпочтения.

C. Сериализация объекта.

D. Класс, который может содержать общие данные, может называться Common Utilities. Это зависит от тебя.

E. Передача данных через намерения и интерфейс Parcelable.

Это зависит от потребностей вашего проекта.

A. База данных

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

Руководства

Б. Общие настройки

Предположим, вы хотите сохранить имя пользователя. Итак, теперь будет две вещи: ключ имя пользователя и значение.

Как хранить

 // 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 (), вы можете сохранить желаемый тип данных.

Как получить

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

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

C. Сериализация объекта

Сериализация объекта используется, если мы хотим сохранить состояние объекта, чтобы отправить его по сети, или вы также можете использовать его для своих целей.

Используйте Java beans и сохраните его как одно из его полей, а для этого используйте геттеры и сеттеры.

JavaBeans - это классы Java, у которых есть свойства. Думайте о свойствах как о частных переменных экземпляра. Поскольку они являются частными, единственный способ получить к ним доступ извне своего класса - это использовать методы в классе. Методы, которые изменяют значение свойства, называются методами установки, а методы, которые получают значение свойства, называются методами получения.

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

Затем используйте сериализацию объекта для сериализации этого объекта и десериализации этого объекта в другом классе.

При сериализации объект может быть представлен как последовательность байтов, которая включает данные объекта, а также информацию о типе объекта и типах данных, хранящихся в объекте.

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

Если вам нужен учебник для этого, обратитесь к:

D. CommonUtilities

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

Образец

public class CommonUtilities {

    public static String className = "CommonUtilities";

}

E. Передача данных через намерения

См. Руководство Android - данные Parcel для передачи между действиями с использованием классов Parcelable для этой опции передачи данных.

person Nikhil Agrawal    schedule 19.05.2013

Создайте свой собственный класс Customer следующим образом:

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

}

В вашем onCreate() методе

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

В классе xyz activity вам нужно использовать следующий код:

Intent intent=getIntent();
Customer cust=(Customer)intent.getSerializableExtra("bundle");
textViewName.setText(cust.getName());
textViewCity.setText(cust.getCity());
person Mayur Chudasama    schedule 21.01.2014
comment
..Проверьте свой код, который вы передаете bundle в качестве ключа для put cust obj и получения из класса .pls используйте один ключ либо class, либо bundle .. - person AK Joshi; 21.11.2014
comment
Я сталкиваюсь с ошибкой: Parcelable обнаружил исключение IOException, записывающее сериализуемый объект - person Arul Mani; 29.03.2019

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

Теперь вы хотите передать объект этого класса в startActivity. Просто используйте это:

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

Здесь это работает, потому что MyClass реализует Serializable.

person Dhiral Pandya    schedule 25.01.2012
comment
не могли бы вы объяснить или уточнить больше - person Amitsharma; 30.09.2016
comment
HomeworkData homeworkData = homeWorksList.get (position); Намерение намерения = новое намерение (c, HomeWorkActivitydetail.class); Пакет b = новый пакет (); b.putSerializable (CompleteData, homeworkData); intent.putExtras (б); c.startActivity (намерение); во время добавления объекта дает мне некоторую ошибку для добавления элементов объекта, мы не можем передать полный объект с этим - person Amitsharma; 30.09.2016
comment
внутри домашней работыДанные у меня есть некоторые значения, которые нужно добавить - person Amitsharma; 30.09.2016

Лучше всего иметь в вашем приложении класс (назовите его Control), который будет содержать статическую переменную типа «Клиент» (в вашем случае). Инициализируйте переменную в своем действии A.

Например:

Control.Customer = CustomerClass;

Затем перейдите к Activity B и получите его из класса Control. Не забудьте присвоить значение null после использования переменной, иначе память будет потрачена впустую.

person Umesh    schedule 29.04.2010
comment
@aez Потому что это небрежно с точки зрения дизайна и ужасно сломается, если намерение когда-либо будет в другом процессе. - person ; 15.01.2013
comment
Вы столкнетесь с проблемами при возобновлении действия вашего приложения до Activity B. Поскольку Activity может быть уничтожено Android, и объект не будет сохранен. - person Ryan R; 18.01.2013

Если вы выберете использование способа, описанного Саму, помните, что можно отправлять только примитивные значения. То есть значения, которые можно парсить. Итак, если ваш объект содержит сложные объекты, они не последуют. Например, такие переменные, как Bitmap, HashMap и т. Д. ... Их сложно передать с помощью намерения.

В общем, я бы посоветовал вам отправлять только примитивные типы данных в качестве дополнительных, например String, int, boolean и т. Д. В вашем случае это будут: String fname, String lname, int age и String address.

Мое мнение: для более сложных объектов лучше использовать ContentProvider, SDCard и т. Д. Также можно использовать статическую переменную, но это может быстро привести к ошибочному коду ...

Но опять же, это всего лишь мое субъективное мнение.

person Vidar Vestnes    schedule 29.04.2010

Я использую parcelable для отправки данных от одного занятия к другому. Вот мой код, который отлично работает в моем проекте.

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

В activityA используйте это так:

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

В ActivityB используйте его для получения данных следующим образом:

Bundle getBundle = this.getIntent().getExtras();
List<Channel> channelsList = getBundle.getParcelableArrayList("channel");
person Bebin T.N    schedule 10.08.2013

Вы можете попробовать использовать этот класс. Ограничение в том, что его нельзя использовать вне одного процесса.

Одно мероприятие:

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

Другая деятельность:

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);
    }
}
person Barbariska    schedule 07.10.2011

Запустите другое действие из этого действия и передайте параметры через объект Bundle

Intent intent = new Intent(getBaseContext(), YourActivity.class);
intent.putExtra("USER_NAME", "[email protected]");
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);
person DroidNinja    schedule 23.06.2017

Этот вопрос также обсуждается в другом вопросе о переполнении стека. Ознакомьтесь с решением для передачи данных через намеренное использование Сериализуемый. Главное - использовать объект Bundle, который хранит необходимые данные внутри Intent.

 Bundle bundle = new Bundle();

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

 intent.putExtras(bundle);

Чтобы извлечь значения:

 Bundle bundle = new Bundle();

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

Преимущество Serializable в простоте. Однако вам следует подумать об использовании метода Parcelable, если вам нужно передать много данных, потому что Parcelable специально разработан для Android и более эффективен, чем Serializable. Вы можете создать класс Parcelable, используя:

  1. онлайн-инструмент - parcelabler
  2. плагин для Android Studio - Генератор кода Android Parcelable
person Ayaz Alifov    schedule 23.02.2015

Создайте класс, подобный классу bean, и реализуйте интерфейс Serializable. Затем мы можем передать его через метод intent, например:

intent.putExtra("class", BeanClass);

Затем получите его из другого действия, например:

BeanClass cb = intent.getSerializableExtra("class");
person Community    schedule 09.02.2014

Создайте два метода в своем пользовательском классе, как это

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

Теперь в вашей активности отправителя сделайте это

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

И в вашей активности приемника

Qabir q =new Qabir();
q.initilizeWithJSONString(getIntent().getStringExtra("obj"));
person Q07    schedule 03.03.2015

Объекты Android Activity можно уничтожать и восстанавливать. Итак, вам нужно будет использовать другой подход для просмотра их - или любого объекта, который они создают !!! - вверх. То есть вы можете передать ссылку на статический класс, но тогда дескриптор объекта (Java вызывает эти ссылки, как и SmallTalk; но они не являются ссылками в смысле C или сборки), возможно, позже станет недействительным, поскольку функция Android OE является любая Деятельность может быть аннигилирована и воссоздана позже.

В исходном вопросе был задан вопрос: «Как передать объект из одного действия в другое в Android», но никто не ответил на этот вопрос. Конечно, вы можете сериализовать (Serializable, Parcelable, в / из JSON) и передать копию данных объекта, и можно будет создать новый объект с такими же данными; но у него НЕ будет одинаковых ссылок / дескрипторов. Кроме того, многие другие упоминали, что вы можете хранить ссылку в статическом хранилище. И это будет работать, если Android не решит уничтожить вашу Activity.

Итак, чтобы действительно решить исходный вопрос, вам понадобится статический поиск, плюс каждый объект будет обновлять свою ссылку, когда / если он будет воссоздан. Например. каждое действие Android будет обновляться, если будет вызвано его onCreate. Вы также можете увидеть, как некоторые люди используют список задач для поиска Activity по имени. (система временно уничтожает этот экземпляр действия, чтобы сэкономить место. getRunningTasks, список задач фактически является специализированным списком самых последних экземпляров объекта каждого действия).

Для справки:

Остановлено: действие полностью скрыто другим действием (действие теперь находится в фоновом режиме). Остановленное действие также остается активным (объект Activity сохраняется в памяти, он поддерживает всю информацию о состоянии и членах, но не прикреплен к диспетчеру окон). Однако он больше не виден пользователю и может быть уничтожен системой, когда память потребуется где-то еще.

Система onDestroy временно уничтожает этот экземпляр активности для экономии места.

Итак, шина сообщений - это работоспособное решение. Это в основном панк. Вместо того, чтобы пытаться иметь ссылки на объекты; затем вы переделываете свой дизайн, чтобы использовать MessagePassing вместо SequentialCode. Экспоненциально сложнее отлаживать; но это позволяет вам игнорировать такого рода понимание операционной среды. Фактически, каждый доступ к методу объекта инвертируется, поэтому вызывающий объект отправляет сообщение, а сам объект определяет обработчик для этого сообщения. Намного больше кода, но можно сделать его более надежным с учетом ограничений Android OE.

Если все, что вам нужно, - это верхняя активность (типичная вещь в приложениях Android из-за того, что контекст требуется везде), тогда вы можете просто указать каждое действие как верхнее в статическом глобальном пространстве при каждом вызове его onResume. Затем ваш AlertDialog или что-то еще, что требует контекста, может просто взять его оттуда. Кроме того, немного неприятно использовать глобальный, но он может упростить передачу контекста вверх и вниз повсюду, и, конечно же, когда вы используете MessageBus, тогда он в любом случае глобален.

person TimJowers2    schedule 05.09.2014
comment
У Отто есть преимущество в том, что он может запускать его извне в простом старом Java-приложении. Так что хорошо для разработки и тестирования без необходимости возиться с Android. У Отто есть большая кривая обучения, и большая часть того, что он решает, уже решена способами Android (локальная трансляция и т. Д.) Или обычными подходами к разработке приложений (вы можете написать гораздо более простой глобальный поиск, чем глобальный поиск Отто, обычные подходы намного более доступный для векторизации / F3 через код и для пошаговой отладки). - person TimJowers2; 08.09.2014

Да, использование статического объекта - это, безусловно, самый простой способ сделать это с помощью нестандартных несериализуемых объектов.

person alistair    schedule 13.05.2011
comment
Да, думаю, я действительно согласен с тобой. Создание этих объектов static - лучший обходной путь, если просто непрактично продолжать вызывать putExtra() для каждого свойства, которое вы хотите передать. Например, прямо сейчас я хочу передать ArrayList, содержащий объекты. Я мог бы вместо этого сделать свой ArrayList static. - person MLQ; 18.08.2011

  1. Я знаю, что статика - это плохо, но, похоже, мы вынуждены здесь ее использовать. Проблема с parceables / seriazables заключается в том, что у двух действий есть повторяющиеся экземпляры одного и того же объекта = трата памяти и ЦП.

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

Вызов активности

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

Вызываемое действие (обратите внимание, что onCreate () и onResume () могут вызываться несколько раз, когда система уничтожает и воссоздает действия)

if (IntentMailBox.content.size()>0)
    level = (Level) IntentMailBox.content.poll();
else
    // Here you reload what you have saved in onPause()
  1. Другой способ - объявить статическое поле класса, который вы хотите передать в этот самый класс. Он будет служить только для этой цели. Не забывайте, что он может иметь значение null в onCreate, потому что ваш пакет приложения был выгружен из памяти системой и перезагружен позже.

  2. Помня, что вам все еще нужно обрабатывать жизненный цикл активности, вы можете захотеть записать все данные прямо в общие настройки, что затруднительно для сложных структур данных как таковых.

person Anton Duzenko    schedule 03.05.2013

Вышеупомянутые ответы почти все верны, но для тех, кто не понимает этих ответов, Android имеет мощный класс Intent, с его помощью вы обмениваетесь данными не только между действиями, но и другими компонентами Android (приемник вещания, услуги для контента при условии, что мы используем класс ContetnResolver без намерения). В своей деятельности вы строите намерение

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

В вашей принимающей деятельности у вас есть

public class SomeActivity extends AppCompactActivity {

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

}

Вы должны реализовать интерфейс Parceable или Serializable для своего объекта, чтобы делиться между действиями. Сложно реализовать интерфейс Parcealbe вместо Serializable на объекте, поэтому в Android есть специальный плагин для этого. Загрузите его и используйте

person dara    schedule 14.03.2017

Я всегда задавался вопросом, почему это не может быть так же просто, как вызов метода другого действия. Недавно я написал служебную библиотеку, которая делает ее почти такой же простой. Вы можете проверить это здесь (https://github.com/noxiouswinter/gnlib_android/wiki/gnlauncher < / а>).

GNLauncher делает отправку объектов / данных в Activity из другого Activity так же просто, как вызов функции в Activity с необходимыми данными в качестве параметров. Он вводит безопасность типов и устраняет все проблемы, связанные с сериализацией, присоединением к намерению с помощью строковых ключей и отменой того же самого на другом конце.

использование

Определите интерфейс с методами, которые вы хотите вызвать для запуска Activity.

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

Реализуйте вышеуказанный интерфейс в Activity, в которую нужно запустить. Также уведомите GNLauncher, когда действие будет готово.

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

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

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

Будет запущено первое действие и вызван метод с необходимыми параметрами.

Предпосылки

См. https://github.com/noxiouswinter/gnlib_android/wiki#prerequisites для информация о том, как добавить зависимости.

person jinais    schedule 02.11.2014

Перенести объект из одного действия в другое.

(1) исходная активность

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

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

(2) активность назначения

List<ArrayList<String>> aa = (List<ArrayList<String>>) getIntent()
            .getSerializableExtra("IntentExamResultDetail");
person Jayesh Kalkani    schedule 13.07.2015

Раньше я устанавливал объект с помощью Pacelable или Serializable для передачи, но всякий раз, когда я добавляю другие переменные к объекту (модели), я должен все это зарегистрировать. Это так неудобно.

Перемещать объект между активностями или фрагментами очень просто.

Android DataCache

person kimkevin    schedule 04.10.2015

Мы можем передать объект из одного действия в другое:

SupplierDetails poSuppliersDetails = new SupplierDetails();

Внутри poSuppliersDetails у нас есть несколько значений. Теперь я отправляю этот объект в целевую активность:

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

Как получить это в ACtivityTwo:

private SupplierDetails supplierDetails;
    supplierDetails =(SupplierDetails) getIntent().getSerializableExtra("poSuppliersDetails");
person Community    schedule 18.11.2015

Передайте одно действие другому:

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

Получите значения:

String myvalue= getIntent().getExtras("passingkey");
person Bhuvaneshwaran Vellingiri    schedule 29.05.2017

Невозможно сериализовать объекты любого типа. Например, вы не можете сериализовать методы делегата или интерфейсы, которые несут код вместо данных. Итак, я написал класс Box, который можно использовать для передачи любого типа данных без сериализации.

1- для целевого использования данных:

Intent I = new Intent(this, YourActivity.class);
CustomClass Date = new CustomClass();
Box.Add(I, "Name", Data);

2- для получения данных из намерения:

CustomClass Data = Box.Get(getIntent(), "Name");

3- для удаления данных после использования добавьте этот метод к своим действиям:

@Override
protected void onDestroy() {
    Box.Remove(getIntent());
    super.onDestroy();
}

4- и добавьте этот код в свой проект:

package ir.namirasoft.Utility;

import android.content.Intent;

import java.util.HashMap;
import java.util.Vector;

public class Box {
    // Number
    private static int Number = 1;

    public static int NextNumber() {
        return Number++;
    }

    //
    private static String _Intent_Identifier = "_Intent_Identifier";
    private static HashMap<Integer, Vector<Integer>> DeleteList = new HashMap<Integer, Vector<Integer>>();
    private static HashMap<Integer, HashMap<String, Object>> ObjectList = new HashMap<Integer, HashMap<String, Object>>();

    public static int GetIntent_Identifier(Intent I) {
        int Intent_Identifier = I.getIntExtra(_Intent_Identifier, 0);
        if (Intent_Identifier == 0)
            I.putExtra(_Intent_Identifier, Intent_Identifier = NextNumber());
        return Intent_Identifier;
    }

    public static void Add(Intent I, String Name, Object O) {
        int Intent_Identifier = GetIntent_Identifier(I);
        synchronized (ObjectList) {
            if (!ObjectList.containsKey(Intent_Identifier))
                ObjectList.put(Intent_Identifier, new HashMap<String, Object>());
            ObjectList.get(Intent_Identifier).put(Name, O);
        }
    }

    public static <T> T Get(Intent I, String Name) {
        int Intent_Identifier = GetIntent_Identifier(I);
        synchronized (DeleteList) {
            DeleteList.remove(Intent_Identifier);
        }
        return (T) ObjectList.get(Intent_Identifier).get(Name);
    }

    public static void Remove(final Intent I) {
        final int Intent_Identifier = GetIntent_Identifier(I);
        final int ThreadID = NextNumber();
        synchronized (DeleteList) {
            if (!DeleteList.containsKey(Intent_Identifier))
                DeleteList.put(Intent_Identifier, new Vector<Integer>());
            DeleteList.get(Intent_Identifier).add(ThreadID);
        }
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(60 * 1000);
                } catch (InterruptedException e) {
                }
                synchronized (DeleteList) {
                    if (DeleteList.containsKey(Intent_Identifier))
                        if (DeleteList.get(Intent_Identifier).contains(ThreadID))
                            synchronized (ObjectList) {
                                ObjectList.remove(Intent_Identifier);
                            }
                }
            }
        }).start();
    }
}

** Класс Box является потокобезопасным.

person Amir Abolhasani    schedule 16.06.2020

Я написал библиотеку под названием intentparser.

Его действительно легко использовать. Добавьте это в свой проект.

allprojects {
        repositories {
            ...
            maven { url 'https://jitpack.io' }
        }
    }

Добавьте это в свое приложение gradle


dependencies {
            implementation 'com.github.lau1944:intentparser:v$currentVersion'
    }

Передать объект с помощью метода расширения putObject

val testModel = TestModel(
            text = "hello world",
            isSuccess = false,
            testNum = 1,
            textModelSec = TextModelSec("second model")
)
startActivity(
     Intent(this, ActivityTest::class.java).apply {
          this.putObject(testModel)
     }
) 

Получить объект из предыдущего действия


val testModel = intent.getObject(TestModel::class.java)
person Jimmy lau    schedule 16.07.2021

Привет всем, я вижу много хороших вариантов, но мне было интересно, почему не использовалась привязка?

Передача ссылки на объект кажется мне более эффективной, чем сериализация и деэтерилизация объектов, но я не делал глубокого погружения, чтобы увидеть, происходит ли это за кулисами.

Создать подшивку достаточно просто ...

public class MyBinder extends Binder {

    private Object myObject;

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

    public Object getObject() {
        return myObject;
    }

}

И создание пакета для использования - это не такой уж и плохой эфир.

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

    };
}

Эта логика действительно хороша, потому что вы фактически передаете ссылку из активности в действие.

Я бы посоветовал проверить наличие нулей, и если instanceof Binder является MyBinder!

и чтобы реализовать это, вы просто ...

Отправь это

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

intent.putExtra("MyParcelable", myParcelable);

Верни это

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

Черт возьми, кто-то может сойти с ума и сделать эту присоску настоящим универсалом.

person SkidRunner    schedule 13.07.2016

Как упоминалось в комментариях, этот ответ нарушает инкапсуляцию и тесно связывает компоненты, что является скорее всего, не то, что вы хотите. Лучшее решение, вероятно, сделать ваш объект Parcelable или Serializable, как объясняют другие ответы. Сказав это, решение решает проблему. Итак, если вы знаете, что делаете:

Используйте класс со статическими полями:

public class Globals {
    public static Customer customer = new Customer();
}

Внутри занятий вы можете использовать:

Активность с:

Globals.customer = myCustomerFromActivity;

Цель деятельности:

myCustomerTo = Globals.customer;

Это простой способ передать информацию о занятиях.

person Dennso    schedule 17.09.2011
comment
Я думаю, что это ужасный ответ, который полностью нарушает инкапсуляцию и тесно связывает компоненты. Правильное решение - использовать parcelable, как указано в одном из ответов ниже. Это ужасная практика !! - person Chris McCabe; 18.12.2014
comment
Иногда инкапсуляция важна, а иногда все уже тесно связано, поэтому на самом деле это не имеет большого значения. Идеализм сам по себе не стоит лишних часов написания кода (плюс дополнительного обслуживания в будущем). Просто осознайте ограничения и возможные проблемы, связанные с этим, а затем решите, стоит ли прилагать дополнительные усилия, чтобы добиться правильного результата в долгосрочной перспективе. - person Brian White; 05.01.2015
comment
Вот как это должно выглядеть: один оператор, который нужно вставить, один оператор, который нужно получить, а не десятки строк шаблонного кода, подверженного ошибкам. - person Yaroslav; 10.03.2015
comment
Это может вызвать проблемы с использованием кнопки возврата. В приведенном выше примере предположим, что у вас есть активность customerDetails. Если в какой-то момент вы разрешите переключение между клиентами, это глобальное значение будет перезаписано, поэтому возврат с помощью кнопки возврата не всегда будет работать должным образом. - person uesports135; 25.04.2015
comment
Если пользователь использует целевое действие, то при изменении другого приложения (открытие уведомлений или выбор изображения из приложения галереи) возможно, что текущее действие будет удалено. Когда пользователь вернется, вы получите исключение с нулевым указателем, поскольку это значение было инициализировано в предыдущем действии. - person El Abogato; 03.05.2015
comment
Есть миллионы успешных коммерческих проектов, которые не полностью следуют идеализму, и +1 Брайану Уайту за то, что он правильно сформулировал. Когда приближается время кризиса, я почти уверен, что более короткое время разработки предпочтительнее незначительного снижения производительности. - person Giridhar Karnik; 26.07.2015
comment
Это взлом. Иногда нам приходится взламывать код, но не тогда, когда есть другие способы сделать это лучше. - person infinite-loop; 31.07.2015