Как отправлять объекты через bundle

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

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

11 ответов


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

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

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

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

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

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


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

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

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

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

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

чиновник документы google также включают пример


вы можете использовать global приложение государство.

обновление:

настроить, а затем добавить это в свой 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; 

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


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


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

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

Класс CustomObject:

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

Subcustom объекты:

class SubCustomObject1 implements Serializable{ }

class SubCustomObject2  implements Serializable{ }

еще один способ отправки объектов через пакет-с помощью bundle.putByteArray
пример кода

public class DataBean implements Serializable {
private Date currentTime;

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

public Date getCurrentTime() {
    return currentTime;
 }
}

поместите объект DataBean в пакет:

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

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


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

приложение

Первый-это приложение, как это было больше всего сказано об ответе здесь. Приложение является хорошим объектом для поместите объекты, которым нужна ссылка на контекст. "ServerSocket", несомненно, потребуется контекст (для ввода-вывода файлов или простых обновлений "ListAdapter"). Лично я предпочитаю этот маршрут. Мне нравятся приложения, они полезны для извлечения контекста (потому что они могут быть статическими и не могут вызвать утечку памяти) и имеют простой жизненный цикл.

сервис

The сервис` второй. "Услуга" на самом деле лучший выбор для моей проблемы, потому что это для чего предназначены сервисы:
A Service is an application component that can perform long-running operations in
the background and does not provide a user interface.
Услугами опрятный в том, что они имеют более определенный жизненный цикл, который легче контролировать. Кроме того, при необходимости службы могут запускаться извне приложения (т. е. при загрузке системы.) Это может потребоваться для некоторых приложений или просто особенность.

это не полное описание, но я оставил ссылки на документы для тех, кто хочет больше разбираться. В целом Service лучше для экземпляра, который мне нужен-запуск ServerSocket для моего SPP устройство.


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

мое предложение, которое даст очень похожий результат, чтобы поместить указанный DataManager в приложение или сделать его Одноэлементным, - это использовать инъекцию зависимостей и привязать DataManager к одноэлементной области и ввести DataManager везде, где это необходимо. Вы не только получаете преимущество повышенной тестируемости, но и получаете более чистый код без использования кода "передача зависимостей между классами и действиями". (Robo)Guice очень легко работать и новый Кинжал рамки выглядят многообещающими.


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

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

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

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

2.передать объект в связке

Bundle bundle = new Bundle();
Object Object = new Object();
bundle.putSerializable("object", object);
  1. получить переданный объект из пакета как сериализуемый, а затем привести к объекту.

    Object object = (Object) getArguments ().getSerializable("объект");