Как отправить объекты через связку - PullRequest
112 голосов
/ 22 ноября 2010

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

Проблема в том, что он не имеет ничего общего с намерениями или контекстами и имеет большое количество не примитивныхобъекты.Как мне упаковать класс в parcelable / serializable и передать его в startActivityForResult?

Ответы [ 11 ]

150 голосов
/ 01 февраля 2013

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

В начальной деятельности

Intent activity = new Intent(MyActivity.this,NextActivity.class);
activity.putExtra("myObject", new Gson().toJson(myobject));
startActivity(activity);

В следующем задании

String jsonMyObject;
Bundle extras = getIntent().getExtras();
if (extras != null) {
   jsonMyObject = extras.getString("myObject");
}
MyObject myObject = new Gson().fromJson(jsonMyObject, MyObject.class);
54 голосов
/ 23 ноября 2010

Чтобы понять, какой путь выбрать, необходимо ответить не только на ключевой вопрос CommonsWare «почему», но и на вопрос «к чему?»Вы передаете его.

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

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

2) Вы можете передать непрозрачную ручку.Если вы передаете его в том же контексте (хотя можно спросить, зачем это нужно), это будет дескриптор, который вы можете вызвать или разыменовать.Но если вы передадите его через Binder в другой контекст, его буквальное значение будет произвольным числом (фактически, эти произвольные числа отсчитываются последовательно от запуска).Вы ничего не можете сделать, кроме как отслеживать это, пока не передадите его обратно в исходный контекст, что заставит Binder преобразовать его обратно в исходный дескриптор, что сделает его снова полезным.

3) Вы можете передатьмагический дескриптор, такой как дескриптор файла или ссылка на определенные объекты os / platform, и, если вы установите правильные флаги, Binder создаст клон, указывающий на тот же ресурс для получателя, который может фактически использоваться на другом конце.Но это работает только для очень немногих типов объектов.

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

19 голосов
/ 23 ноября 2010

Интерфейс Parcelable - это хороший способ передать объект с помощью Intent.

Как я могу сделать свои собственные объекты Parcelable? - довольно хороший ответ о том, как использовать Parcelable

Официальные Google Документы также включают пример

14 голосов
/ 22 ноября 2010

Вы можете использовать глобальное приложение состояние.

Обновление:

Настройте и добавьте это в свой AndroidManifest.xml:

<application android:label="@string/app_name" android:debuggable="true" android:name=".CustomApplication"

А затем в вашем проекте есть такой класс:

package com.example;

import android.app.Application;

public class CustomApplication extends Application {
    public int someVariable = -1;
}

И поскольку « Доступ к нему можно получить через getApplication () из любого действия или службы », вы используете его так:

CustomApplication application = (CustomApplication)getApplication();
application.someVariable = 123; 

Надеюсь, это поможет.

11 голосов
/ 23 ноября 2010

Вы также можете сделать свои объекты Сериализуемыми и использовать методы getSerializable и putSerializable в комплекте.

10 голосов
/ 14 декабря 2015

Возможное решение:

Bundle bundle = new Bundle();
bundle.putSerializable("key", new CustomObject());

Класс CustomObject:

class CustomObject implements Serializable{
 private SubCustomObject1 sc1;
 private SubCustomObject2 sc2;
}

Объекты под заказ:

class SubCustomObject1 implements Serializable{ }

class SubCustomObject2  implements Serializable{ }
7 голосов
/ 11 декабря 2012

Еще один способ отправки объектов через связку - использование bundle.putByteArray
Пример кода

public class DataBean implements Serializable {
private Date currentTime;

public setDate() {
    currentTime = Calendar.getInstance().getTime();
 }

public Date getCurrentTime() {
    return currentTime;
 }
}

положить объект DataBean в Bundle:

class FirstClass{
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Your code...

//When you want to start new Activity...
Intent dataIntent =new Intent(FirstClass.this, SecondClass.class);
            Bundle dataBundle=new Bundle();
            DataBean dataObj=new DataBean();
            dataObj.setDate();
            try {
                dataBundle.putByteArray("Obj_byte_array", object2Bytes(dataObj));

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();

            }

            dataIntent.putExtras(dataBundle);

            startActivity(dataIntent);
}

Преобразование объектов в байтовые массивы

/**
 * Converting objects to byte arrays
 */
static public byte[] object2Bytes( Object o ) throws IOException {
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      ObjectOutputStream oos = new ObjectOutputStream( baos );
      oos.writeObject( o );
      return baos.toByteArray();
    }

Получить объект обратно из комплекта:

class SecondClass{
DataBean dataBean;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Your code...

//Get Info from Bundle...
    Bundle infoBundle=getIntent().getExtras();
    try {
        dataBean = (DataBean)bytes2Object(infoBundle.getByteArray("Obj_byte_array"));
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

Метод получения объектов из байтовых массивов:

/**
 * Converting byte arrays to objects
 */
static public Object bytes2Object( byte raw[] )
        throws IOException, ClassNotFoundException {
      ByteArrayInputStream bais = new ByteArrayInputStream( raw );
      ObjectInputStream ois = new ObjectInputStream( bais );
      Object o = ois.readObject();
      return o;
    }

Надеюсь, это поможет другим друзьям.

1 голос
/ 21 августа 2018

1.Очень прямой и простой в использовании пример: передаваемый объект реализует Serializable.

class Object implements Serializable{
    String firstName;
   String lastName;
}

2.pass объект в связке

Bundle bundle = new Bundle();
Object Object = new Object();
bundle.putSerializable("object", object);

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

Object object = (Object) getArguments (). GetSerializable ("object");

0 голосов
/ 24 декабря 2015

еще один простой способ передать объект с помощью пакета:

  • в объекте класса создайте статический список или другую структуру данных с ключом
  • когда вы создаете объект, поместите его в список / структуру данных с ключом (например, длинная метка времени при создании объекта)
  • создать статический метод getObject (длинный ключ) для получения объекта из списка
  • в связке передайте ключ, чтобы вы могли получить объект позже из другого пункта кода
0 голосов
/ 08 февраля 2013

Я столкнулся с этим вопросом, когда искал способ передать объект Date. В моем случае, как было предложено среди ответов, я использовал Bundle.putSerializable (), но это не сработало бы для такой сложной вещи, как описанный DataManager в исходном посте.

Мое предложение, которое даст очень похожий результат на размещение указанного DataManager в Приложении или превращение его в Singleton, заключается в использовании Dependency Injection и привязке DataManager к области действия Singleton и внедрении DataManager, где это необходимо. Вы не только получите выгоду от улучшенной тестируемости, но также получите более чистый код без всякой базовой схемы «передачи зависимостей между классами и действиями». (Robo) Guice очень прост в работе, и новый фреймворк Dagger также выглядит многообещающе.

...