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

612

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

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

  • 1
    вероятно, вам следует изменить принятый ответ с учетом массового мнения.
  • 0
    Раньше я устанавливал для объекта значение Pacelable или Serializable, но всякий раз, когда я добавляю другие переменные, мне приходится добавлять все это в функции, чтобы получить и установить для Pacelable или Serializable. поэтому я сделал DataCache для переноса между действиями и фрагментами. github.com/kimkevin/AndroidDataCache Переносить объекты очень просто.
Теги:
object
android-activity
android-intent

31 ответ

657
Лучший ответ

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

псевдокод

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

// To retrieve object in second Activity
getIntent().getSerializableExtra("MyClass");
  • 1
    У меня такая же ситуация, после того, как я реализовал Serializable, должен ли я делать что-то особенное в своем классе, должен ли я реализовывать некоторые методы?
  • 117
    @OD: В свою защиту я никогда не говорил, что это лучший вариант; ОП просто попросил альтернативы, и я предложил один. В любом случае спасибо.
Показать ещё 15 комментариев
238

Внедрите свой класс с помощью 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");

Что это.

  • 1
    Это было действительно полезно для меня. Спасибо ... Но при получении переданного объекта синтаксис должен быть [Deneme dene = (Deneme) i.getSerializableExtra ("sampleObject"); ] ... Это ???
  • 1
    @ MustafaGüven Но я получаю classCastException: java.lang.Long , делая это. Не могли бы вы объяснить, почему?
Показать ещё 6 комментариев
93
  • Использование глобальных статических переменных не является хорошей практикой разработки программного обеспечения.
  • Преобразование полей объекта в примитивные типы данных может быть тяжелой работой.
  • Использование сериализуемого кода в порядке, но оно неэффективно на платформе Android.
  • Parcelable специально предназначен для Android, и вы должны его использовать. Вот простой пример: Передача пользовательских объектов между действиями Android

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

  • 3
    Что если мой объект содержит вложенный Arraylist?
  • 9
    Ну, может быть, но на самом деле нужно воспринимать «производительность» с недоверием. Если это Parcelable с ценой реализации Parcelable то я бы предпочел, чтобы мои классы POJO не Parcelable Android, и использовал бы Serializable .
Показать ещё 6 комментариев
83

При вызове операции

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();
    }
  • 0
    Адхаван, у меня есть вопрос. Когда вы создаете первый класс Intent, вы передаете fromClass.this в качестве первого аргумента. Есть ли способ получить этот объект в получающем классе активности?
  • 1
    Милиу, fromClass fr = (fromClass) getParent (); это то, что тебе нужно?
Показать ещё 4 комментария
70

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

  • Реализация Parcelable

  • Реализация Serializable

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

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

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

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

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

  • 4
    Ссылка на статью мертва. Все еще доступно в веб- архиве : web.archive.org/web/20160917213123/http://…
  • 0
    Спасибо за вашу помощь
Показать ещё 4 комментария
51

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

Пример:

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

И в следующем упражнении, где вы хотите передать объект:

Gson gson = new Gson();
YourObject ob = gson.fromJson(getIntent().getStringExtra("myjson"), YourObject.class);
  • 3
    Это избыточное решение, gson - это просто тип сериализации строк в json, лучше реализовать Serializable или Paracable.
  • 11
    Нет необходимости реализовывать сериализуемый в каждом объекте и в каждом проекте (пустая трата времени), если вы можете использовать библиотеку (gson), которая обрабатывает это. Что касается излишеств, то есть двух- и четырехъядерных телефонов, они могут обрабатывать даже список, следуя этой идее ответа.
Показать ещё 8 комментариев
37

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

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

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, но таким образом это яснее, на мой взгляд. Кроме того, вы можете установить временные ивары temp равными нулю, чтобы скорее очистить GarbageCollector.

Удачи!

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

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

String fName = getIntent().getExtras().getInt("fname");
  • 9
    вернуть ваши данные снова с помощью: String fName = getIntent (). getExtras (). getInt ("fname");
  • 2
    Чтобы вернуть данные: Bundle extras = getIntent().getExtras(); String val = extras.getString("fname");
Показать ещё 4 комментария
27

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

  • НЕТ ПОСЛЕДНИЕ
  • НЕТ Serializable
  • НЕТ статического поля
  • Нет шины событий

Метод 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-объекта нет ссылки. связующее сохраняет эту глобальную ссылку JNI в объекте Binder.

* ПРЕДОСТЕРЕЖЕНИЕ: этот метод ТОЛЬКО работает, если два действия не выполняются в одном и том же процессе, иначе бросают ClassCastException в (ObjectWrapperForBinder) getIntent(). getExtras(). getBinder ( "object_value" ) *

class ObjectWrapperForBinder defining

public class ObjectWrapperForBinder extends Binder {

    private final Object mData;

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

    public Object getData() {
        return mData;
    }
}

Метод 2

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

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

Способ 3

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

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 выглядит не достаточно простым, потому что мы должны реализовать интерфейс helpl. Если вы просто хотите выполнить простую задачу, а возвращаемое значение метода не нужно, мы можем использовать 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);
}
  • 0
    Извините, я не видел, что у вас был обязательный ответ, и я чувствую, что ваш ответ тоже очень элегантный.
25

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

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

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

  • 1
    Отличная идея! Дополнительно может быть, вы можете создать дополнительный класс ObjectContainer {Object, obj; логический перманент; ....} Идея в том, что вы можете передать логический метод в методе add, если вам нужно сохранить объект постоянным и не удалять при вызове get. Это поможет сохранить некоторые глобальные объекты. Как может быть открытое соединение Bluetooth и т. Д.
  • 1
    Милый, но не изобретай велосипед. Модель автобуса элегантна и мощнее. Смотрите мой пост ниже.
Показать ещё 3 комментария
23

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

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

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

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

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

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

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

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

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

Как получить

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

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

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

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

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

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

public class VariableStorage implements Serializable  {

    private String inString;

    public String getInString() {
        return inString;
    }

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

Задайте переменную в методе почты с помощью

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

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

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

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

Если вы хотите, чтобы учебник для этого ссылался на:

Д. CommonUtilities

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

Пример

public class CommonUtilities {

    public static String className = "CommonUtilities";

}

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

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

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

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

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

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

  • 0
    не могли бы вы объяснить или уточнить подробнее
  • 0
    HomeworkData homeworkData = homeWorksList.get (position); Intent intent = new Intent (c, HomeWorkActivitydetail.class); Bundle b = новый Bundle (); b.putSerializable ("CompleteData", homeworkData); intent.putExtras (б); c.startActivity (намерение); во время добавления объекта дает мне некоторую ошибку для добавления элементов объекта, мы можем не передать полный объект с этим
Показать ещё 1 комментарий
15

Лучший способ - иметь класс (назовите его "Управление" ) в своем приложении, в котором будет храниться статическая переменная типа "Клиент" (в вашем случае). Инициализируйте переменную в своей активности A.

Например:

Control.Customer = CustomerClass;

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

  • 4
    @aez Потому что это небрежно с точки зрения дизайна и ужасно сломается, если Intent когда-либо будет в другом процессе.
  • 6
    Вы столкнетесь с проблемами при возврате приложения в действие B. Поскольку действие может быть убито Android, и объект не будет сохранен.
14

Создайте свой собственный класс 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;
    }

}

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

@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());
  • 0
    ..Проверьте код, который вы передаете "bundle" в качестве ключа для put cust obj и получаете из "class" .. Пожалуйста, используйте один ключ "class" или "bundle" ..
  • 0
    Я сталкиваюсь с ошибкой: Parcelable столкнулся с IOException при записи сериализуемого объекта
10

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

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

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

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

8

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

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

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

Одно действие:

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

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

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

Этот вопрос также обсуждается в другом вопросе. Посмотрите решение для передачи данных с помощью 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, используя:

5

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

intent.putExtra("class", BeanClass);

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

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

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

Intent intent = new Intent(getBaseContext(), YourActivity.class);
intent.putExtra("USER_NAME", "[email protected]");
startActivity(intent);

Извлечь данные о другой активности (YourActivity)

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

Это нормально для простого типа данных. Но если вы хотите передать сложные данные между действиями. U необходимо сначала выполнить сериализацию.

Здесь у нас есть модель сотрудника

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);
  • 0
    TypeToken <> устарел. Что за альтернатива?
3

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

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

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

Для справки:

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

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

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

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

  • 0
    У Отто есть возможность запускать его внешне в простом старом Java-приложении. Так что, хорошо для разработки и тестирования без необходимости связываться с Android. У Otto есть большая кривая обучения, и большая часть того, что он решает, уже решена способами Android (локальная трансляция и т. Д.) Или обычными подходами разработчиков приложений (вы можете написать гораздо более простой глобальный поиск, чем глобальный поиск Otto, нормальные подходы намного более доступным для векторизации / F3 через код и для пошаговой отладки).
3

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

  • 0
    Да, я думаю, что на самом деле согласен с вами. Сделать эти объекты static - лучший обходной путь, если просто нецелесообразно продолжать putExtra() для каждого свойства, которое вы хотите передать. Например, сейчас я хочу передать ArrayList который содержит объекты. Я мог бы также сделать мой ArrayList static вместо этого.
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. Принимая во внимание, что вам все еще нужно обрабатывать жизненный цикл деятельности, вы можете записать все данные прямо на общие настройки, болезненно со сложными структурами данных, как есть.

0

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

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

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

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

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

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 интерфейс на объекте, который специально для этого имеет плагин. Загрузите его и используйте

0

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

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

Создание связующего достаточно просто...

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

    };
}

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

Я бы посоветовал проверить нули и если экземпляр 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();

Если кто-то может сойти с ума и сделать этот сосун истинным родовым.

0

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

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

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

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

Android DataCache

0

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

(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

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

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

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.

-19

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

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

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

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

Деятельность От:

Globals.customer = myCustomerFromActivity;

Целевая задача:

myCustomerTo = Globals.customer;

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

  • 151
    Я думаю, что это ужасный ответ, который полностью разрушает инкапсуляцию и тесно связывает компоненты. Правильное решение - использовать parcelable, как указано в одном из ответов ниже. Это ужасная практика !!
  • 31
    Иногда инкапсуляция важна, а иногда вещи уже тесно связаны, так что это действительно мало что меняет. Один только идеализм не стоит часов дополнительного кодирования (плюс больше технического обслуживания в будущем). Просто осознайте ограничения и возможные проблемы, связанные с этим, и затем решите, стоит ли в долгосрочной перспективе больше усилий, чтобы быть «правильными».
Показать ещё 6 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню