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


Estoy tratando de trabajar en enviar un objeto de mi cliente clase de uno Activity y 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 desde uno Activity a otro y luego mostrar los datos en el otro Activity.

¿Cómo puedo lograr eso?


606
2018-04-29 10:06


origen


Respuestas:


Una opción podría ser permitir que su clase personalizada implemente Serializable interfaz y luego puede pasar instancias de objeto en la intención extra utilizando el putExtra(Serializable..) variante de Intent#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 la interfaz Serializable para evitar excepciones de serialización. Por ejemplo:

class MainClass implements Serializable {

    public MainClass() {}

    public static class ChildClass implements Serializable {

        public ChildClass() {}
    }
}

721
2018-04-29 10:39



Implementa tu 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 dene de actividad X a 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, obtenemos el objeto.

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

Eso es.


264
2017-10-19 20:19



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

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


103
2018-04-16 18:50



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

83
2017-08-03 08:42



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

  1. Implementando Parcelable

  2. Implementando Serializable

  3. Uso de una biblioteca de autobuses de eventos livianos de algún tipo (por ejemplo, GreenBow's EventBus o Square's Otto)

Parcelable - estándar rápido y Android, pero tiene muchos códigos repetitivos y requiere cadenas codificadas para referencia cuando se extraen los valores de la intención (no fuertemente tipados).

Serializable - texto casi cero, pero es el enfoque más lento y también requiere cadenas codificadas cuando extrae los valores del intento (no fuertemente tipado).

Autobús de eventos - Complemento cero, el enfoque más rápido, y no requiere cadenas codificadas, pero sí una dependencia adicional (aunque generalmente es liviano, ~ 40 KB)

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


70
2017-11-18 19:36



Utilizar gson para convertir su objeto a JSON y pasarlo a través de la intención. En la nueva actividad convierte el JSON en un objeto.

En tus build.gradle, agrega esto a tus dependencias

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

En tu Actividad, convierte el objeto a json-string:

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

En su Actividad de recepción, convierta la json-string de nuevo en el objeto original:

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

59
2017-10-31 07:08



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

Pero si solo quieres mostrarlos, y no usar el objeto en otro método o algo así, debería ser suficiente. Lo hice de la misma manera para simplemente 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 temp ivars, pero de esta manera es más claro, en mi opinión. Además, puede configurar los tiempos para anular para que LimpiaCollector 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 recuperas tus datos en otra actividad:

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

37
2018-04-29 11:27



Encontré un método simple y elegante:

  • NO Parcelable
  • NO Serializable
  • NO campo estático
  • Sin 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);

usted encontrará objSent & objReceived tener lo mismo hashCode, entonces son idénticos

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

En realidad, la carpeta de Android creará referencia JNI global para el objeto java y lanzará esta referencia JNI global cuando no haya referencia para este objeto java. Binder guardará esta referencia JNI global en el objeto Binder.

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

clase ObjectWrapperForBinder defination

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. utilice un método nativo personalizado para agregar su objeto java a la tabla de referencia global JNI (a través de JNIEnv :: NewGlobalRef)
    2. pon el entero de retorno (en realidad, JNIEnv :: NewGlobalRef return jobject, que es un puntero, podemos convertirlo a int de forma segura) en tu Intent (a través de Intent :: putExtra)
  • para el receptor
    1. obtener un número entero de Intent (a través de Intent :: getInt)
    2. utiliza un método nativo personalizado para restaurar tu objeto java desde la tabla de referencia global JNI (a través de JNIEnv :: NewLocalRef)
    3. eliminar el elemento de la tabla de referencia global JNI (a través de JNIEnv :: DeleteGlobalRef),

Pero el Método 2 tiene un pequeño pero serio problema, si el receptor no restaura el objeto java (por ejemplo, ocurre alguna excepción antes de restaurar el objeto java, o la actividad del receptor no existe), entonces el objeto Java se convertirá en un objeto huérfano o pérdida de memoria, El método 1 no tiene este problema, porque el encuadernador de Android 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, utilizaremos 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 forma, podemos pasar una interfaz entre dos actividades aunque se ejecuten en un proceso diferente, y llamar el método de interfaz de forma remota

Método 4

el método 3 parece no ser lo suficientemente simple porque debemos implementar una interfaz de ayuda. Si solo quiere hacer una tarea simple y el valor de retorno del método no es necesario, 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();
        }

    }
}

Todo el Messenger.send se ejecutará en un controlador de forma asíncrona y secuencial.

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

package android.os;

import android.os.Message;

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

29
2018-06-12 13:46



Hice una clase de ayudante 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 tu nueva actividad, puedes obtener el objeto:

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

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


24
2018-06-20 13:20



Hay un par de formas en las que 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 se puede nombrar como Utilidades comunes. Depende de ti.

E. Pasar 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 de bases de datos relacionales estándar como sintaxis SQL, transacciones y declaraciones preparadas.

Tutoriales

SEGUNDO. Preferencias compartidas

Supongamos que desea almacenar el nombre de usuario. Entonces ahora habrá dos cosas, una llave nombre de usuario, 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

DO. 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 beans Java y almacénelo como uno de sus campos y use getters y setter para eso.

JavaBeans son clases de Java que tienen propiedades. Pensar en propiedades como variables de instancia privadas. Como son privados, la única manera se puede acceder desde fuera de su clase 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 usa la serialización de objetos para serializar este objeto y en tu otra clase deserializar este objeto.

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

Después de escribir un objeto serializado 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:

RE. CommonUtilities

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

Muestra

public class CommonUtilities {

    public static String className = "CommonUtilities";

}

MI. Pasar datos a través de intentos

Por favor, consulte el tutorial Android: datos de parcelas para pasar entre Actividades utilizando clases Parcelable para esta opción de pasar datos.


23
2018-05-19 20:00



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

Por ejemplo:

Control.Customer = CustomerClass;

Luego vaya a la Actividad B y descárguelo de la clase Control. No olvide asignar un valor nulo después de usar la variable; de ​​lo contrario, la memoria se desperdiciará.


15
2018-04-29 12:09