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

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

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

Ответ 1

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

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

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

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

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

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

Ответ 2

Вы также можете использовать 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);

Ответ 4

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

Update:

Настройте, а затем добавьте это в свой 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() из любого Activity или Service", вы используете его следующим образом:

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

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

Ответ 6

Еще один способ отправить объекты через пакет - с помощью 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();
    }

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

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

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

Ответ 7

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

Bundle bundle = new Bundle();
bundle.putSerializable(new CustomObject());

Класс CustomObject:

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

Объекты subcustom:

class SubCustomObject1 implements Serializable{ }

class SubCustomObject2  implements Serializable{ }

Ответ 8

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

Ответ 9

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

Применение

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

Сервис

Сервис является вторым. "Служба" на самом деле является лучшим выбором для моей проблемы, потому что именно эти сервисы предназначены для работы:
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.

Ответ 10

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

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

Ответ 11

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

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