Cómo pasar un objeto de una actividad a otra en Android


780

Estoy tratando de trabajar para enviar un objeto de mi clase de cliente desde uno Activityy mostrarlo en otro Activity.

El código para la clase de cliente:

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

Quiero enviar su objeto de uno Activitya otro y luego mostrar los datos en el otro Activity.

¿Cómo puedo lograr eso?


1
probablemente debería cambiar la respuesta aceptada en vista de la opinión masiva.
Rohit Vipin Mathews

Solía ​​establecer el objeto en Pacelable o Serializable, pero cada vez que agrego otras variables, tengo que agregarlo todo a las funciones para obtener y establecer Pacelable o Serializable. así que hice DataCache para transferir entre actividades y fragmentos. github.com/kimkevin/AndroidDataCache Es muy fácil transferir objetos.
kimkevin

Respuestas:


887

Una opción podría ser dejar que su clase personalizada implemente la Serializableinterfaz y luego puede pasar instancias de objetos en la intención adicional utilizando la putExtra(Serializable..)variante deIntent#putExtra() método.

Pseudocódigo :

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

// To retrieve object in second Activity
getIntent().getSerializableExtra("MyClass");

Nota: Asegúrese de que cada clase anidada de su clase personalizada principal haya implementado una interfaz serializable para evitar cualquier excepción de serialización. Por ejemplo:

class MainClass implements Serializable {

    public MainClass() {}

    public static class ChildClass implements Serializable {

        public ChildClass() {}
    }
}

126
@OD: En mi defensa, nunca dije que esta fuera la mejor opción; OP solo pidió alternativas y sugerí una. Gracias de todos modos.
Samuh

83
¿Por qué Serializable no es una buena opción? Es una interfaz bien conocida, existe una buena posibilidad de que las clases populares ya la implementen (ArrayList, por ejemplo, ya es serializable). ¿Por qué debería tener que cambiar sus objetos de datos para agregar código adicional simplemente para pasarlos de una clase a otra? Eso parece un mal diseño. Me imagino que puede haber algún impacto en el rendimiento en algún nivel, pero creo que en el 99% de los casos, las personas pasan pequeñas cantidades de datos y no les importará. Más simple y portátil a veces es mejor también.
Nate

16
@Sander: ¿Esta respuesta ( stackoverflow.com/questions/2139134/… ) es incorrecta entonces? Él dice que Parcelable ES específicamente diseñado para ese propósito (y mucho más rápido que Serializable). Estoy confundido
Slauma

41
Parcelablepuede ser bueno para la velocidad, pero es complicado de implementar. ¿Qué pasa si tiene 8 objetos que necesita pasar entre actividades, va a hacer cada uno Parcelable? Tendría más sentido usar Serializableen su lugar. Cuando implementa Parcelable, debe agregar mucho código a la clase y ordenar los campos de una manera muy específica; Serializableusted no En última instancia, creo que se trata de cuántos objetos está pasando y qué está tratando de hacer.
BlackHatSamurai

15
Serializablees una interfaz estándar de Java. Simplemente marque una clase Serializable implementando la interfaz, y Java la serializará automáticamente en ciertas situaciones. Parcelablees una interfaz específica de Android donde implementas la serialización tú mismo. Fue creado para ser mucho más eficiente que Serializable, y para solucionar algunos problemas con el esquema de serialización Java predeterminado
Gaurav Arora

312

Implemente su clase con Serializable. Supongamos que esta es su clase de entidad:

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

Estamos enviando el objeto llamado denede la actividad X a la actividad Y. En algún lugar de la actividad X;

Deneme dene = new Deneme(4,"Mustafa");
Intent i = new Intent(this, Y.class);
i.putExtra("sampleObject", dene);
startActivity(i);

En la actividad Y estamos obteniendo el objeto.

Intent i = getIntent();
Deneme dene = (Deneme)i.getSerializableExtra("sampleObject");

Eso es.


1
Fue realmente útil para mí. Gracias ... Pero al recibir el objeto pasado, la sintaxis debe ser [Deneme dene = (Deneme) i.getSerializableExtra ("sampleObject"); ] ... Lo es ???
JibW

1
@ MustafaGüven Pero lo estoy haciendo classCastException: java.lang.Longal hacerlo. ¿Puedes explicar por qué?
Shajeel Afzal

No hay ninguna relación con mi respuesta. Es algo muy diferente lo que estás recibiendo. ¿Podrías compartir tus códigos?
Mustafa Güven

1
Serializable es demasiado lento para POJO grandes. Usar un autobús es un patrón mucho mejor.
Steven Mark Ford

1
¿Por qué debería tener que prefijar (Serializable)al objeto?
Alston

123
  • Usar variables estáticas globales no es una buena ingeniería de software práctica de .
  • Convertir los campos de un objeto en tipos de datos primitivos puede ser un trabajo agitado .
  • Usar serializable está bien, pero no es eficiente en rendimiento en en la plataforma Android.
  • Parcelable está específicamente diseñado para Android y debe usarlo. Aquí hay un ejemplo simple: pasar objetos personalizados entre actividades de Android

Puede generar código Parcelable para su clase usando este sitio .


44
¿Qué sucede si mi objeto contiene una Arraylist anidada?
Dr. aNdRO

10
Bueno, tal vez, pero uno realmente debería tomar `` rendimiento '' con un grano de sal imo. Si eso tiene un precio de implementación Parcelable, prefiero mantener mis clases de POJO con uso de Android Serializable.
VH-NZZ

No estoy de acuerdo con que debas usar Parcelable. Un patrón de BUS simple es mucho más eficiente en tiempo de ejecución y ahorra muchísimo tiempo de desarrollo.
Steven Mark Ford

15
Según este punto de referencia, bitbucket.org/afrishman/androidserializationtest Serializable es mucho más rápido que Parcelable. Por favor, deja de compartir estas tonterías de 5 años sobre Parcelable.
Afr.

77
¿Cómo son las variables estáticas globales "no una buena práctica de ingeniería de software"? Puede hacer algo como una caché de singleton y / o una cuadrícula de datos y luego pasar identificaciones o similares. Cuando pasa referencias en Java, está utilizando variables estáticas globales en cierto sentido, ya que apuntan al mismo objeto.
corte

112

Usar gson para convertir su objeto a JSON y pasarlo por intención. En la nueva Actividad, convierta el JSON en un objeto.

En su build.gradle, agregue esto a sus dependencias

implementation 'com.google.code.gson:gson:2.8.4'

En su Actividad, convierta el objeto a json-string:

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

En su Actividad receptora, convierta la cadena json nuevamente al objeto original:

Gson gson = new Gson();
YourObject ob = gson.fromJson(getIntent().getStringExtra("myjson"), YourObject.class);

Para Kotlin es casi lo mismo

Pasar los datos

val gson = Gson()
val intent = Intent(this, YourActivity::class.java)
intent.putExtra("identifier", gson.toJson(your_object))
startActivity(intent)

Recibe los datos

val gson = Gson()
val yourObject = gson.fromJson<YourObject>(intent.getStringExtra("identifier"), YourObject::class.java)

3
Es una exageración, gson es solo un tipo de serialización de cadenas para json, es mejor implementar Serializable o Paracable.
James Roeiter

14
No hay necesidad de implementar serializable en cada objeto y en cada proyecto (pérdida de tiempo) si puede usar una biblioteca (gson) que maneje eso. Y sobre la exageración, hay teléfonos duales y cuádruples, pueden manejar incluso una lista siguiendo esta idea de respuesta.
cede

44
También recomendaría usar gson porque gson también puede serializar listas de matrices además de las anteriores.
nurgasemetey

44
¡Esto es genial! En mi caso, estoy usando una biblioteca que los objetos no implementan serializable o parcelable. Así que esta es mi única opción afaik
Chad Bingham

2
Esta es la mejor opcion. Algunas clases son tan simples que no es necesario complicar demasiado su implementación implementando serializable
Ojonugwa Jude Ochalifu

98

Mientras llama a una actividad

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

En toClass.java recibe la actividad por

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

Asegúrese de que la clase de cliente implemente parcelable

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

Adhavan, tengo una pregunta. Cuando crea la primera clase Intent, pasa fromClass.this como primer argumento. ¿Hay alguna manera de recuperar este objeto en la clase de actividad receptora?
newman

1
Miliu, fromClass fr = (fromClass) getParent (); ¿Es esto lo que necesitabas?
Anuncios del

Adhava, en realidad hice esto, pero fr es nulo. ¿Alguna idea de por qué?
newman

miliu, comparta su rastro de excepción para que podamos analizarlo.
Anuncios

Parcelable tiene muchísimos códigos innecesarios de placa de caldera y, francamente, es una pérdida de tiempo. Más bien usa un autobús. Vea mi publicación a continuación.
Steven Mark Ford

89

En mi experiencia, hay tres soluciones principales, cada una con sus desventajas y ventajas:

  1. Implementando Parcelable

  2. Implementando Serializable

  3. Usar una biblioteca de bus de eventos liviana de algún tipo (por ejemplo, el EventBus de Greenrobot o el Otto de Square)

Parcelable : rápido y estándar de Android, pero tiene un montón de código repetitivo y requiere cadenas codificadas para referencia cuando extrae valores de la intención (sin tipear).

Serializable : placa repetitiva cercana a cero, pero es el enfoque más lento y también requiere cadenas codificadas al extraer valores de la intención (sin tipear).

Event Bus : cero repetitivo, enfoque más rápido y no requiere cadenas codificadas, pero sí requiere una dependencia adicional (aunque generalmente es liviana, ~ 40 KB)

Publiqué una comparación muy detallada sobre estos tres enfoques, incluidos los puntos de referencia de eficiencia.


44
El enlace al artículo está muerto. Todavía disponible en webarchive: web.archive.org/web/20160917213123/http://…
OlivierH

Es una pena que el enlace esté caído :(
Mauker

El problema del uso de Event Bus es cuando la Actividad objetivo se recrea debido a la rotación, por ejemplo. En este caso, la Actividad objetivo no tiene acceso al objeto pasado porque este objeto fue consumido desde el bus por una llamada anterior.
JuliuszJ

1
Parcelable es el más rápido y con este generador ( parcelabler.com ), puede pegar su clase y puede generar el código por usted. Simple.
PorWaleed

1
@ ByWaleed ... Estoy totalmente de acuerdo, siempre uso este sitio, hace cosas sin problemas. Sin embargo, he tenido muchos intentos fallidos cuando trato de usar un POJO que está compuesto de otro Objeto. Por alguna razón, su salida no funciona realmente.
Yo Apps

42

Encontré un método simple y elegante:

  • NO parcelable
  • NO serializable
  • NO campo estático
  • No hay bus de eventos

Método 1

Código para la primera actividad:

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

Código para la segunda actividad:

    final Object objReceived = ((ObjectWrapperForBinder)getIntent().getExtras().getBinder("object_value")).getData();
    Log.d(TAG, "received object=" + objReceived);

encontrarás objSenty objReceivedtendrás lo mismohashCode , por lo que son idénticos.

Pero, ¿por qué podemos pasar un objeto Java de esta manera?

En realidad, Android Binder creará una referencia JNI global para el objeto Java y liberará esta referencia JNI global cuando no haya ninguna referencia para este objeto Java. Binder guardará esta referencia JNI global en el objeto Binder.

* PRECAUCIÓN: este método SOLO funciona a menos que las dos actividades se ejecuten en el mismo proceso; de lo contrario, arroje ClassCastException en (ObjectWrapperForBinder) getIntent (). GetExtras (). GetBinder ("object_value") *

clase ObjectWrapperForBinder definición

public class ObjectWrapperForBinder extends Binder {

    private final Object mData;

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

    public Object getData() {
        return mData;
    }
}

Método 2

  • para el remitente
    1. use un método nativo personalizado para agregar su objeto java a la tabla de referencia global JNI (a través de JNIEnv :: NewGlobalRef)
    2. coloque el entero de retorno (en realidad, JNIEnv :: NewGlobalRef return jobject, que es un puntero, podemos enviarlo a int de forma segura) a su Intención (a través de Intent :: putExtra)
  • para el receptor
    1. obtener entero de Intent (a través de Intent :: getInt)
    2. use un método nativo personalizado para restaurar su objeto java desde la tabla de referencia global JNI (a través de JNIEnv :: NewLocalRef)
    3. eliminar elemento de la tabla de referencia global JNI (a través de JNIEnv :: DeleteGlobalRef),

Pero el Método 2 tiene un problema pequeño pero grave, si el receptor no puede restaurar el objeto java (por ejemplo, ocurre alguna excepción antes de restaurar el objeto java, o la Actividad del receptor no existe en absoluto), entonces el objeto java se convertirá en un huérfano o pérdida de memoria, el Método 1 no tiene este problema, ya que Android Binder manejará esta excepción

Método 3

Para invocar el objeto java de forma remota, crearemos un contrato / interfaz de datos para describir el objeto java, usaremos el archivo aidl

IDataContract.aidl

package com.example.objectwrapper;
interface IDataContract {
    int func1(String arg1);
    int func2(String arg1);
}

Código para la primera actividad

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

Código para la segunda actividad:

cambie el atributo android: process en AndroidManifest.xml a un nombre de proceso no vacío para asegurarse de que la segunda actividad se ejecute en otro proceso

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

De esta manera, podemos pasar una interfaz entre dos actividades a pesar de que se ejecutan en un proceso diferente, y llamar al método de la interfaz de forma remota

Método 4

El método 3 no parece lo suficientemente simple porque debemos implementar una interfaz de ayuda. Si solo desea realizar una tarea simple y el valor de retorno del método es innecesario, podemos usar android.os.Messenger

Código para la primera actividad (remitente):

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

Código para la segunda actividad (receptor):

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

    }
}

Todos los Messenger.send se ejecutarán en un controlador de forma asincrónica y secuencial.

En realidad, android.os.Messenger también es una interfaz de ayuda, si tiene el código fuente de Android, puede encontrar un archivo llamado IMessenger.aidl

package android.os;

import android.os.Message;

/** @hide */
oneway interface IMessenger {
    void send(in Message msg);
}

Lo siento, no vi que tu respuesta también fuera vinculante. Creo que tu respuesta también es muy elegante.
SkidRunner

Wow ... El primer método de este hombre es tremendo ..... Cuando tienes objetos muy grandes / grandes que funcionan bien
karan

Yo uso el método uno. Entonces, me ahorras tiempo. Gracias;
ShweLiam

Muchas gracias por el método ObjectWrapperForBinder, ¡realmente ayuda!
Vladimir Tolstikov

40

También puede escribir los datos del objeto en cadenas e ints temporales, y pasarlos a la actividad. Por supuesto, de esa manera, se transportan los datos, pero no el objeto en sí.

Pero si solo desea mostrarlos, y no usar el objeto en otro método o algo así, debería ser suficiente. Lo hice de la misma manera para mostrar datos de un objeto en otra actividad.

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

También podría pasarlos directamente en lugar de los ivars temporales, pero de esta manera es más claro, en mi opinión. Además, puede configurar los ivars temporales como nulos para que GarbageCollector los limpie antes.

¡Buena suerte!

En una nota al margen: anule toString () en lugar de escribir su propio método de impresión.

Como se menciona en los comentarios a continuación, así es como recupera sus datos en otra actividad:

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

99
recupere sus datos nuevamente con: String fName = getIntent (). getExtras (). getInt ("fname");
Alister

2
Para recuperar los datos: Bundle extras = getIntent().getExtras(); String val = extras.getString("fname");
Eric Leschinski

1
Esto puede volverse inviable rápidamente para POJO grandes. Más bien usa un autobús. Vea mi publicación a continuación.
Steven Mark Ford

Como mencioné en mi respuesta, esto es para casos de uso simples donde no necesita el objeto en sí, sino solo algunos valores del mismo. No es una solución para casos de uso complejos.
MJB

1
Buena idea para pasar un solo objeto, pero estoy tratando de pasar una matriz de tamaño desconocido de mi objeto. Quizás su solución no sea para pasar matrices de objetos.
Muhammad Saqib

25

Hice una clase de ayuda singleton que contiene objetos temporales.

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

En lugar de poner sus objetos dentro de Intent, use IntentHelper:

IntentHelper.addObjectForKey(obj, "key");

Dentro de su nueva Actividad, puede obtener el objeto:

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

Tenga en cuenta que una vez cargado, el objeto se elimina para evitar referencias innecesarias.


1
¡Buena idea! Además, puede crear una clase adicional ObjectContainer {Object, obj; permanente booleano; ....} La idea es que puede pasar un método booleano en agregar si necesita mantener el objeto persistente y no eliminarlo cuando llamamos a get. Ayudará a mantener algunos objetos globales. Como puede ser una conexión bluetooth abierta etc
Umair

1
Lindo pero no reinventes la rueda. El patrón del autobús es elegante y más potente. Vea mi publicación a continuación.
Steven Mark Ford

@StevenMarkFord, ¿el patrón de Bus sigue siendo válido hasta el día de hoy? Estoy tratando de mejorar una base de código con un código como este para acceder a datos entre actividades: BookActivity.getInstance().recommendationResponseenRoomsActivity
Woppi

Cuando se recrea la Actividad receptora (por ejemplo, en la rotación de la pantalla) se objconvierte null. Para evitar esto, objdebe almacenarse en algún lugar para obtenerlo nuevamente. De hecho, la solución Json almacena datos de objetos en Intent.
Salvador

25

Hay un par de formas por las cuales puede acceder a variables u objetos en otras clases o actividades.

A. Base de datos

B. Preferencias compartidas.

C. serialización de objetos.

D. Una clase que puede contener datos comunes puede denominarse Utilidades comunes. Depende de ti.

E. Transferencia de datos a través de Intentos e Interfaz Parcelable.

Depende de las necesidades de su proyecto.

A. Base de datos

SQLite es una base de datos de código abierto que está integrada en Android. SQLite admite características estándar de bases de datos relacionales como sintaxis SQL, transacciones y declaraciones preparadas.

Tutoriales

SI. Preferencias compartidas

Supongamos que desea almacenar el nombre de usuario. Así que ahora habrá dos cosas, un nombre de usuario clave , valor valor.

Cómo almacenar

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

Usando putString (), putBoolean (), putInt (), putFloat () y putLong () puede guardar su tipo de dta deseado.

Cómo buscar

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

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

C. serialización de objetos

La serlización de objetos se usa si queremos guardar un estado de objeto para enviarlo a través de una red o también puede usarlo para su propósito.

Use Java Beans y almacene en él como uno de sus campos y use getters y setter para eso.

JavaBeans son clases Java que tienen propiedades. Piense en las propiedades como variables de instancia privada. Como son privados, la única forma en que se puede acceder desde fuera de su clase es a través de métodos en la clase. Los métodos que cambian el valor de una propiedad se llaman métodos setter, y los métodos que recuperan el valor de una propiedad se llaman métodos getter.

public class VariableStorage implements Serializable  {

    private String inString;

    public String getInString() {
        return inString;
    }

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

Establezca la variable en su método de correo usando

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

Luego use la serialización de objetos para serializar este objeto y en su otra clase deserialice este objeto.

En la serialización, un objeto puede representarse como una secuencia de bytes que incluye los datos del objeto, así como información sobre el tipo de objeto y los tipos de datos almacenados en el objeto.

Después de que un objeto serializado se haya escrito en un archivo, se puede leer del archivo y deserializarlo. Es decir, la información de tipo y los bytes que representan el objeto y sus datos se pueden usar para recrear el objeto en la memoria.

Si desea un tutorial para esto, consulte:

D. Utilidades comunes

Puede hacer una clase usted mismo que puede contener datos comunes que necesita con frecuencia en su proyecto.

Muestra

public class CommonUtilities {

    public static String className = "CommonUtilities";

}

E. Pasando datos a través de intentos

Consulte el tutorial Android: datos de parcelas para pasar entre actividades usando clases parcelables para esta opción de pasar datos.


22

Crea tu propia clase de la Customersiguiente manera:

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

}

En su onCreate()metodo

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

En xyz activityclase necesitas usar el siguiente código:

Intent intent=getIntent();
Customer cust=(Customer)intent.getSerializableExtra("bundle");
textViewName.setText(cust.getName());
textViewCity.setText(cust.getCity());

..Compruebe su código que está pasando "bundle" como clave para poner obj cust y obtener de "class" .. por favor use una clave ya sea "class" o "bundle" ..
AK Joshi

Me enfrento a un error: Parcelable encontró IOException al escribir un objeto serializable
Arul Mani

15

La mejor manera es tener una clase (llámela Control) en su aplicación que contendrá una variable estática de tipo 'Cliente' (en su caso). Inicialice la variable en su Actividad A.

Por ejemplo:

Control.Customer = CustomerClass;

Luego vaya a la Actividad B y recójalo desde la clase Control. No olvide asignar un valor nulo después de usar la variable, de lo contrario se desperdiciará memoria.


44
@aez Porque es descuidado desde el punto de vista del diseño y se romperá horriblemente si la intención se encuentra en otro proceso.

77
Tendrá problemas al reanudar su aplicación a la Actividad B. Dado que la Actividad puede ser eliminada por Android y el objeto no se guardará.
Ryan R

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

Ahora desea pasar el objeto de esta clase en startActivity. Simplemente use esto:

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

Esto funciona aquí porque MyClass implementa Serializable.


¿podría explicar o explicar más
Amitsharma

HomeworkData homeworkData = homeWorksList.get (posición); Intención intención = nueva intención (c, HomeWorkActivitydetail.class); Bundle b = nuevo Bundle (); b.putSerializable ("CompleteData", homeworkData); intent.putExtras (b); c. startActivity (intento); en un momento en que agregar objeto me da algún error al agregar elementos de objeto, ¿no podemos pasar el objeto completo con esto
Amitsharma

dentro de la tarea
Datos que

12

Si elige usar la forma que describe Samuh, recuerde que solo se pueden enviar valores primitivos. Es decir, valores que son parcables. Entonces, si su objeto contiene objetos complejos, estos no seguirán. Por ejemplo, variables como Bitmap, HashMap, etc. Son difíciles de pasar por la intención.

En general yo le asesoramiento para enviar tipos de datos primitivos solamente como extras, como String, int, boolean, etc., en su caso sería: String fname, String lname, int age, yString address .

Mi opinión: los objetos más complejos se comparten mejor implementando un ContentProvider , SDCard , etc. También es posible usar una variable estática , pero esto puede conducir rápidamente a un código propenso a errores ...

Pero de nuevo, es solo mi opinión subjetiva.


8

Estoy usando parcelable para enviar datos de una actividad a otra actividad. Aquí está mi código que funciona bien en mi proyecto.

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

En la actividad A úsalo así:

Bundle bundle = new Bundle();
bundle.putParcelableArrayList("channel",(ArrayList<Channel>) channels);
Intent intent = new Intent(ActivityA.this,ActivityB.class);
intent.putExtras(bundle);
startActivity(intent);

En ActivityB úsalo así para obtener datos:

Bundle getBundle = this.getIntent().getExtras();
List<Channel> channelsList = getBundle.getParcelableArrayList("channel");

7

Puedes intentar usar esa clase. La limitación es que no se puede usar fuera de un proceso.

Una actividad:

 final Object obj1 = new Object();
 final Intent in = new Intent();
 in.putExtra(EXTRA_TEST, new Sharable(obj1));

Otra actividad:

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

6

Inicie otra actividad desde esta actividad y pase parámetros a través del objeto Bundle

Intent intent = new Intent(getBaseContext(), YourActivity.class);
intent.putExtra("USER_NAME", "xyz@gmail.com");
startActivity(intent);

Recuperar datos sobre otra actividad (YourActivity)

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

Esto está bien para un tipo simple de tipo de datos. Pero si quieres pasar datos complejos entre actividades. Necesitas serializarlo primero.

Aquí tenemos el modelo de empleado

class Employee{
    private String empId;
    private int age;
    print Double salary;

    getters...
    setters...
}

Puede usar Gson lib proporcionado por google para serializar datos complejos como este

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

TypeToken <> está en desuso. ¿Cuál es la alternativa?
Ragavendra M

6

Esta pregunta también se discute en otra pregunta de desbordamiento de pila. Eche un vistazo a una solución para pasar datos a través de la intención utilizando Serializable . El punto principal es sobre el uso de Bundleobjetos que almacenan los datos necesarios dentro Intent.

 Bundle bundle = new Bundle();

 bundle.putSerializable(key1, value1);
 bundle.putSerializable(key2, value2);
 bundle.putSerializable(key3, value3);

 intent.putExtras(bundle);

Para extraer valores:

 Bundle bundle = new Bundle();

 for (String key : bundle.keySet()) {
 value = bundle.getSerializable(key));
 }

La ventaja de Serializablees su simplicidad. Sin embargo, debe considerar el uso del Parcelablemétodo si necesita transferir muchos datos, ya que Parcelableestá específicamente diseñado para Android y es más eficiente que Serializable. Puedes crear una Parcelableclase usando:

  1. una herramienta en línea - parcelabler
  2. un complemento para Android Studio - Generador de código parcelable de Android

5

Cree una clase como bean class e implemente la Serializableinterfaz. Luego podemos pasarlo por el intentmétodo, por ejemplo:

intent.putExtra("class", BeanClass);

Luego obténgalo de la otra actividad, por ejemplo:

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

5

Cree dos métodos en su clase personalizada como esta

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

Ahora en tu actividad de remitente haz esto

Qabir q= new Qabir(22,"KQ");    
Intent in=new Intent(this,SubActivity.class);
in.putExtra("obj", q.toJSON());
startActivity( in);

Y en tu receptor Actividad

Qabir q =new Qabir();
q.initilizeWithJSONString(getIntent().getStringExtra("obj"));

3

Sí, usar un objeto estático es, con mucho, la forma más fácil de hacerlo con objetos personalizados no serializables.


Sí, creo que estoy de acuerdo contigo. Hacer esos objetos statices la mejor solución si simplemente no es práctico seguir invocando putExtra()para cada propiedad que le gustaría transmitir. Por ejemplo, en este momento, quiero pasar un ArrayListque contiene objetos. También podría hacer mi ArrayList en su staticlugar.
Matthew Quiros

3

Los objetos de actividad de Android se pueden destruir y reconstituir. Por lo tanto, tendrá que usar otro enfoque para mirarlos , ¡o cualquier objeto que creen ! - arriba. Es decir, podría pasar como referencia de clase estática, pero luego el identificador de objeto (Java llama a estas "referencias", al igual que SmallTalk; pero no son referencias en el sentido de C o ensamblaje) posiblemente no sea válido más adelante porque una "característica" de Android OE es cualquier actividad que se pueda aniquilar y reconstituir más tarde.

La pregunta original era "Cómo pasar objetos de una actividad a otra en Android" y nadie ha respondido eso. Por supuesto, puede serializar (Serializable, Parcelable, hacia / desde JSON) y pasar una copia de los datos del objeto y se podría crear un nuevo objeto con los mismos datos; pero NO tendrá las mismas referencias / identificadores. Además, muchos otros mencionaron que puede almacenar la referencia en una tienda estática. Y eso funcionará a menos que Android decida onDestroy su actividad.

Por lo tanto, para resolver realmente la pregunta original, necesitaría una búsqueda estática y cada objeto actualizará su referencia cuando / si se vuelve a crear. Por ejemplo, cada actividad de Android se volvería a listar si se llama a onCreate. También puede ver cómo algunas personas usan la lista de tareas para buscar una Actividad por nombre. (el sistema está destruyendo temporalmente esta instancia de la actividad para ahorrar espacio ... getRunningTasks, la lista de tareas es efectivamente una lista especializada de la instancia de objeto más reciente de cada Actividad).

Para referencia:

Detenido: "La actividad está completamente oculta por otra actividad (la actividad ahora está en el" fondo "). Una actividad detenida también sigue viva (el objeto Actividad se retiene en la memoria , mantiene toda la información del estado y de los miembros, pero no está adjunto al administrador de ventanas). Sin embargo, ya no es visible para el usuario y el sistema puede matarlo cuando se necesita memoria en otro lugar ".

onDestroy "el sistema está destruyendo temporalmente esta instancia de la actividad para ahorrar espacio".

Entonces, el bus de mensajes es una solución viable. Básicamente "tira". En lugar de tratar de tener referencias a objetos; luego rediseña su diseño para usar MessagePassing en lugar de SequentialCode. Exponencialmente más difícil de depurar; pero le permite ignorar este tipo de comprensión del entorno operativo. Efectivamente, cada acceso al método de objeto se invierte para que la persona que llama publique un Mensaje y el objeto mismo defina un controlador para ese mensaje. Mucho más código, pero puede hacerlo robusto con las restricciones de Android OE.

Si todo lo que desea es la Actividad superior (algo típico en las aplicaciones de Android debido a que se necesita "Contexto" en todas partes), entonces puede hacer que cada Actividad se enumere a sí misma como "superior" en el espacio global estático cada vez que se llama a onResume. Entonces su AlertDialog o lo que sea que necesite un contexto puede simplemente tomarlo desde allí. Además, es un poco asqueroso usar un global, pero puede simplificar pasar un Contexto hacia arriba y hacia abajo en todas partes y, por supuesto, cuando usa un MessageBus, entonces ES global de todos modos.


Otto tiene la capacidad de ejecutarlo externamente en una aplicación Java simple y antigua. Entonces, bueno para desarrolladores y pruebas sin tener que meterse con Android. Otto tiene una gran curva de aprendizaje y la mayor parte de lo que resuelve ya está resuelto en Android (transmisión local, etc.) o en enfoques normales de desarrollo de aplicaciones (puede escribir una búsqueda global mucho más simple que la búsqueda global de Otto, los enfoques normales son mucho más accesible para vectorización / F3 a través del código y para pasar por la depuración).
TimJowers2

2
  1. Sé que la estática es mala, pero parece que estamos obligados a usarla aquí. El problema con parceables / seriazables es que las dos actividades tienen instancias duplicadas del mismo objeto = pérdida de memoria y CPU.

    public class IntentMailBox {
        static Queue<Object> content = new LinkedList<Object>();
    }

Actividad de llamada

IntentMailBox.content.add(level);
Intent intent = new Intent(LevelsActivity.this, LevelActivity.class);
startActivity(intent);

Actividad llamada (tenga en cuenta que onCreate () y onResume () pueden llamarse varias veces cuando el sistema destruye y recrea actividades)

if (IntentMailBox.content.size()>0)
    level = (Level) IntentMailBox.content.poll();
else
    // Here you reload what you have saved in onPause()
  1. Otra forma es declarar un campo estático de la clase que desea pasar en esa misma clase. Servirá solo para este propósito. No olvide que puede ser nulo en onCreate, porque su paquete de aplicaciones ha sido descargado de la memoria por el sistema y recargado más tarde.

  2. Teniendo en cuenta que aún necesita manejar el ciclo de vida de la actividad, es posible que desee escribir todos los datos directamente en las preferencias compartidas, doloroso con las estructuras de datos complejas como son.


1

Las respuestas anteriores son casi todas correctas, pero para aquellos que no entienden esas respuestas, Android tiene una Intención de clase poderosa con la ayuda de que usted comparte datos entre no solo la actividad sino también otros componentes de Android (receptor de radiodifusión, servicios para contenido siempre que usemos la clase ContetnResolver sin Intención ) En tu actividad construyes intención

Intent intent = new Intent(context,SomeActivity.class);
intent.putExtra("key",value);
startActivity(intent);

En tu actividad de recepción tienes

public class SomeActivity extends AppCompactActivity {

    public void onCreate(...){
    ...
          SomeObject someObject = getIntent().getExtras().getParceable("key");
    }

}

Debe implementar una interfaz Parceable o Serializable en su objeto para compartir entre actividades. Es difícil implementar Parcealbe en lugar de una interfaz serializable en un objeto, por eso Android tiene un complemento especialmente para esto. Descárguelo y úselo


0

Siempre me pregunté por qué esto no puede ser tan simple como llamar a un método de la otra actividad. Recientemente escribí una biblioteca de utilidades que lo hace casi tan simple como eso. Puede consultarlo aquí ( https://github.com/noxiouswinter/gnlib_android/wiki/gnlauncher ).

GNLauncher hace que enviar objetos / datos a una Actividad desde otra Actividad, etc., sea tan fácil como llamar a una función en esa Actividad con los datos requeridos como parámetros. Introduce la seguridad de tipos y elimina todas las molestias de tener que serializar, unir a la intención utilizando teclas de cadena y deshacer la misma en el otro extremo.

Uso

Defina una interfaz con los métodos que desea llamar en la Actividad para iniciar.

public interface IPayload {
    public void sayHello(String name, int age);
}

Implemente la interfaz anterior en la Actividad para iniciar. También notifique a GNLauncher cuando la actividad esté lista.

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

En la otra Actividad, obtenga un proxy de la Actividad anterior y llame a cualquier método con los parámetros deseados.

public class Activity_2 extends Activity {
    public void onClick(View v) {
        ((IPayload)GNLauncher.get().getProxy(this, IPayload.class, Activity_1.class)).sayHello(name, age);
    }
}

Se iniciará la primera actividad y se llamará al método con los parámetros requeridos.

Prerrequisitos

Consulte https://github.com/noxiouswinter/gnlib_android/wiki#prerequisites para obtener información sobre cómo agregar las dependencias.


0

Pase el objeto de una actividad a otra actividad.

(1) actividad fuente

Intent ii = new Intent(examreport_select.this,
                    BarChartActivity.class);

            ii.putExtra("IntentExamResultDetail",
                    (Serializable) your List<ArraList<String>> object here);
            startActivity(ii);

(2) actividad de destino

List<ArrayList<String>> aa = (List<ArrayList<String>>) getIntent()
            .getSerializableExtra("IntentExamResultDetail");

0

Solía ​​establecer objetos con Pacelable o Serializable para transferir, pero cada vez que agrego otras variables al objeto (modelo), tengo que registrarlo todo. Es muy poco conveniente.

Es muy fácil transferir objetos entre actividades o fragmentos.

Android DataCache


0

Podemos pasar el objeto de una actividad a otra actividad:

SupplierDetails poSuppliersDetails = new SupplierDetails();

En el interior poSuppliersDetailstenemos algunos valores. Ahora estoy enviando este objeto a la actividad objetivo:

Intent iPODetails = new Intent(ActivityOne.this, ActivityTwo.class);
iPODetails.putExtra("poSuppliersDetails", poSuppliersDetails);

Cómo conseguir esto en ACtivityTwo:

private SupplierDetails supplierDetails;
    supplierDetails =(SupplierDetails) getIntent().getSerializableExtra("poSuppliersDetails");

0

Pase una actividad a otra:

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

Obtener valores:

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

-1

Hola a todos, veo muchas buenas opciones, pero me preguntaba por qué no se ha utilizado Binding.

Pasar una referencia a un objeto me parece más eficiente que serializar y desterilizar objetos, pero no he profundizado para ver si eso es lo que está sucediendo detrás de escena.

Crear una carpeta es bastante simple ...

public class MyBinder extends Binder {

    private Object myObject;

    public MyBinder(Object object) {
        myObject = object;
    }

    public Object getObject() {
        return myObject;
    }

}

Y crear el parcelable para usarlo no es ese éter malo.

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

    };
}

Esta lógica es realmente genial porque en realidad estás pasando una referencia de una actividad a otra.

¡Recomendaría comprobar si hay nulos y si la instancia de Binder es MyBinder!

y para implementar esto solo ...

Enviarlo

Object myObject = "some object";
MyParcelable myParcelable = new MyParcelable();
myParcelable.setObject(myObject);

intent.putExtra("MyParcelable", myParcelable);

Recuperar

myParcelable = (MyParcelable) getIntent().getExtras().getParcelable("MyParcelable");
myObject = myParcelable.getObject();

Diablos, alguien podría volverse loco y hacer de este imbécil un verdadero genérico.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.