web-dev-qa-db-fra.com

Problème: transmission de données volumineuses à la deuxième activité

J'ai un problème étrange. Je regardais autour du Web mais je n'ai pas trouvé de réponse. Je suis toujours un débutant en programmation Android. Alors allons-y:

Tout ce que je veux faire, c'est appeler la deuxième activité avec des données. Cela fonctionne très bien avec de petites données, mais si les données deviennent volumineuses, la deuxième activité ne s'affichera pas et la première se terminera. Voici mon code de la méthode d'appel:

Intent intent = new Intent(ActivitySearch.this,ActivityResults.class);
Bundle bundle = new Bundle();
bundle.putParcelableArrayList("data", searchList);
intent.putExtras(bundle);
startActivity(intent);

La partie de la réception des données n'est pas importante. Même si je n'essaie pas de lire le bundle, l'activité ne sera pas appelée. J'ai testé cela avec les lignes suivantes:

@Override
public void onCreate(Bundle savedInstanceState) {
Log.d("DEBUG","ActivityResult::onCreate()");
super.onCreate(savedInstanceState);

OnCreate() n'est jamais appelé.

Peut-être que l'un des vôtres a eu une idée ... Merci de votre aide!

Edit: au moins j'ai oublié: cela ne se produit que sous ICS. L'application fonctionne comme un charme avec du pain d'épice et du froyo.

Edit2: Logcat

10-10 14:49:46.951: D/OpenGLRenderer(21696): Flushing caches (mode 0)
10-10 14:49:47.011: V/ActivityThread(22429): com.example.amazonsearch white listed for hwui
10-10 14:49:50.821: W/IInputConnectionWrapper(21696): showStatusIcon on inactive InputConnection
34
sk2andy

Vous obtenez probablement TransactionTooLargeException

Comme suggéré par Google guide Android , vous pouvez utiliser des champs statiques ou des singletons pour partager des données entre les activités.

Ils le recommandent "Pour partager des objets définis par l'utilisateur complexes non persistants pendant une courte durée"

D'après votre code, il semble que c'est exactement ce dont vous avez besoin.

Ainsi, votre code dans ActivitySearch.class pourrait ressembler à ceci:

ActivityResults.data = searchList;
Intent intent = new Intent(ActivitySearch.this,ActivityResults.class);
startActivity(intent);

Ensuite, vous pouvez accéder à ActivityResults.data de n'importe où dans l'activité ActivityResults après son démarrage.

Pour les données qui doivent être partagées entre les sessions utilisateur, il n'est pas conseillé d'utiliser des champs statiques, car le processus d'application pourrait être tué et redémarré par Android framework pendant que l'application s'exécute en arrière-plan (si le framework doit Dans ce cas, tous les champs statiques seront réinitialisés.

46
Igor B.

La façon dont je préfère transmettre des données volumineuses consiste à utiliser des énumérations . Quelques avantages de cette approche:

  • Pas besoin de créer de singletons, vous avez toujours une seule instance de votre énumération;
  • Les données sont correctement encapsulées;
  • La référence est supprimée juste après que l'activité l'a reçue

Voici un exemple:

package com.jyvee.arguments;

import Java.util.List;

import Android.app.Activity;
import Android.content.Context;
import Android.content.Intent;
import Android.os.Bundle;

public class SomeActivity extends Activity {

    // Names for the arguments we pass to the
    // activity when we create it
    private final static String ARG_STRING = "ARG_STRING";
    private final static String ARG_INT = "ARG_INT";

    private String stringField;
    private int intField;
    private List<Object> arrayField;

    private enum DataHolder {
        INSTANCE;

        private List<Object> mObjectList;

        public static boolean hasData() {
            return INSTANCE.mObjectList != null;
        }

        public static void setData(final List<Object> objectList) {
            INSTANCE.mObjectList = objectList;
        }

        public static List<Object> getData() {
            final List<Object> retList = INSTANCE.mObjectList;
            INSTANCE.mObjectList = null;
            return retList;
        }
    }

    @Override
    protected void onCreate(final Bundle savedState) {
        super.onCreate(savedState);

        // Get the activity intent if there is a one
        final Intent intent = getIntent();

        // And retrieve arguments if there are any
        if (intent.hasExtra(ARG_STRING)) {
            stringField = intent.getExtras().getString(ARG_STRING);
        }
        if (intent.hasExtra(ARG_INT)) {
            intField = intent.getExtras().getInt(ARG_INT);
        }
        // And we retrieve large data from enum
        if (DataHolder.hasData()) {
            arrayField = DataHolder.getData();
        }

        // Now stringField, intField fields are available
        // within the class and can be accessed directly
    }

    /**
     * /** A static method for starting activity with supplied arguments
     * 
     * @param contextA
     *            context that starts this activity
     * @param stringArg
     *            A string argument to pass to the new activity
     * @param intArg
     *            An int argument to pass to the new activity
     * @param objectList
     *            An object list argument to pass to the new activity
     */
    public static void startActivity(final Context context, final String stringArg, 
            final int intArg, final List<Object> objectList) {

        // Initialize a new intent
        final Intent intent = new Intent(context, SomeActivity.class);

        // To speed things up :)
        intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);

        // And add arguments to the Intent
        intent.putExtra(ARG_STRING, stringArg);
        intent.putExtra(ARG_INT, intArg);

        // Now we put the large data into our enum instead of using Intent extras
        DataHolder.setData(objectList);

        context.startActivity(intent);
    }
}

Plus d'informations ici .

28
Rahim

Si vous transmettez une grande information d'une activité à une autre, cela peut ralentir l'application

mais utilisez Global Class pour stocker des variables en utilisant que vous pouvez facilement obtenir ou définir toutes les valeurs

qui a déclaré dans le fichier global

voir ce lien:

http://androidresearch.wordpress.com/2012/03/22/defining-global-variables-in-Android/

3
Akash

Pour autant que je m'en souvienne, jusqu'à l'API-8 (Froyo), il y avait certaines limitations (comme 1 Mo) lors du passage d'objets parcelables à travers des intentions. Cependant, vous pouvez simplement noter vos données parcellaires dans un fichier et envoyer le chemin du fichier à votre prochaine activité via le bundle. Plus tard, codez votre deuxième activité pour lire les données du fichier et supprimez-les ensuite.

2
waqaslam

Je ne sais pas pourquoi cela ne fonctionne pas avec des données volumineuses, mais si vous ne trouvez aucun moyen de le corriger, je vous suggère d'utiliser une application globale personnalisée, comme ici . (Vérifiez également la bonne réponse pour que cela fonctionne)

1
Leandroid