it-swarm.com.ru

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

Я пытаюсь отправить объект моего покупателя класса из одного 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.

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

662
kaibuki

Один из вариантов может позволить вашему пользовательскому классу реализовать интерфейс Serializable, а затем вы можете передать экземпляры объекта в дополнительные намерения, используя вариант 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() {}
    }
}
780
Samuh

Реализуйте свой класс с 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");

Вот и все.

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

Вы можете сгенерировать Parcelable-код для своего класса, используя этот site .

109
SohailAziz

Во время вызова деятельности 

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

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

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

Пожалуйста, убедитесь, что класс клиента реализует

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

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

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

  2. Реализация Сериализуемый

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

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

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

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

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

79
Steven Mark Ford

Используйте gson , чтобы преобразовать ваш объект в JSON и передать его через намерение. В новом Activity конвертируйте 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);

Получив Activity, преобразуйте 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)
76
khalid

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

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

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

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

Удачи!

На заметку: переписать toString () вместо написания собственного метода печати.

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

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

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

  • НЕТ Parcelable
  • НЕТ Сериализуемый
  • НЕТ статического поля
  • No Event Bus

Способ 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

  • для отправителя
    1. используйте собственный нативный метод для добавления вашего Java-объекта в глобальную справочную таблицу JNI (через JNIEnv :: NewGlobalRef)
    2. поместите возвращаемое целое число (фактически, JNIEnv :: NewGlobalRef возвращаемое задание, являющееся указателем, мы можем безопасно преобразовать его в int) в ваше намерение (через Intent :: putExtra)
  • для получателя
    1. получить целое число из Intent (через Intent :: getInt) 
    2. используйте собственный нативный метод для восстановления вашего Java-объекта из глобальной справочной таблицы JNI (через JNIEnv :: NewLocalRef)
    3. удалить элемент из глобальной справочной таблицы JNI (через JNIEnv :: DeleteGlobalRef),

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

Способ 3

Для удаленного вызова Java-объекта мы создадим контракт данных/интерфейс для описания Java-объекта и будем использовать файл aidl.

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

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

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

Внутри вашей новой деятельности вы можете получить объект:

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

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

25
Roger Sanoli

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

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

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

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

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

E. Передача данных через Intents и Parcelable Interface.

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

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

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

Учебники

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

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

Как хранить

 // 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-бины и сохраняйте их как одно из его полей, а для этого используйте getter и setter.

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

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 - Данные посылки для передачи между действиями с использованием классов Parcelable для этой опции передачи данных.

23
Nikhil Agrawal

Создайте свой собственный класс 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());
18
Mayur Chudasama
public class MyClass implements Serializable{
    Here is your instance variable
}

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

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

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

15
Dhiral Pandya

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

Например:

Control.Customer = CustomerClass;

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

15
Umesh

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

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

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

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

12
Vidar Vestnes

Я использую 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});
    }
}

В деятельности A используйте это так:

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");
8
Bebin T.N

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

Один вид деятельности:

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

Этот вопрос также обсуждается в другом вопросе переполнения стека. Пожалуйста, посмотрите на решение Передача данных через намерение с использованием Serializable . Суть в том, чтобы использовать объект 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 
6
Sa Qada

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

intent.putExtra("class", BeanClass);

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

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

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

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"));
5
Q07

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

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

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

3
alistair

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

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

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

Для справки:

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

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

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

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

3
TimJowers2
  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. Другой способ - объявить статическое поле класса, который вы хотите передать в этом классе. Это будет служить только для этой цели. Не забывайте, что он может быть нулевым в onCreate, потому что ваш пакет приложения был выгружен из памяти системой и перезагружен позже.

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

2
Anton Duzenko

Вышеуказанные ответы почти все правильные, но для тех, кто не понимает эти ответы Android имеет мощный класс Намерение с его помощью вы обмениваетесь данными не только с действиями, но и с другими компонентами 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 имеет плагин специально для этого. Скачайте его и используйте его

1
Sardor Islomov

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

(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");
0
Jayesh Kalkani

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

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");
0
user4715375

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

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

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

String myvalue= getIntent().getExtras("passingkey");
0
Bhuvaneshwaran Vellingiri

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

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

Android DataCache

0
kimkevin

Я всегда задавался вопросом, почему это не может быть так просто, как вызов метода другой деятельности. Недавно я написал служебную библиотеку, которая делает его почти таким же простым. Вы можете проверить это здесь ( 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 для получения информации о том, как добавить зависимости. 

0
jinais