2012-10-10 4 views
24

Ho uno strano problema. Stavo guardando in tutto il web ma non ho trovato una risposta. Sono ancora un principiante nella programmazione Android. Quindi andiamo:Problema: passaggio di dati di grandi dimensioni alla seconda attività

Tutto quello che voglio fare è chiamare la seconda attività con alcuni dati. Funziona bene con dati piccoli, ma se i dati diventano grandi, la seconda attività non verrà visualizzata e il primo termina. Ecco il mio codice del metodo chiamante:

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

La parte di ricezione dei dati non è importante. Anche se non provo a leggere il pacchetto, l'attività non verrà chiamata. Ho provato questo con i seguenti linee:

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

OnCreate() ottiene mai chiamato.

Forse uno dei tuoi ha avuto un'idea ... Grazie per il vostro aiuto!

Modifica: almeno ho dimenticato: questo succede solo in ICS. L'app funziona come un vero fascino con il pan di zenzero e il 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 
+0

Bene, in questo caso è necessario avere uno stacktrace in LogCat. Si prega di controllare e scaricare qualche registro degli errori. –

+0

va bene allegato al post. Grazie per questa rapida risposta! – sk2andy

+1

Ci saranno di più. Qui non riesco a vedere nessuna informazione rilevante –

risposta

33

Probabilmente si sta ottenendo TransactionTooLargeException

Come suggerito da Google android guide, è possibile utilizzare i campi o single statici per condividere i dati tra le attività.

Essi raccomandano che "Per la condivisione non persistenti oggetti definiti dall'utente complesse per breve durata"

dal codice sembra che è esattamente quello che vi serve.

Quindi, il codice in ActivitySearch.class potrebbe essere simile a questa:

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

Quindi è possibile accedere ActivityResults.data da qualsiasi attività ActivityResults dopo l'avvio.

Per i dati che devono essere condivisi tra le sessioni utente, non è consigliabile utilizzare i campi statici, poiché il processo dell'applicazione potrebbe essere eliminato e riavviato dal framework Android mentre l'app è in esecuzione in background (se il framework necessita di risorse libere). In tal caso, tutti i campi statici verranno reinizializzati.

+2

Che cosa succede se desideri inviare dati di grandi dimensioni tra diverse app o processi? –

+0

Sì, TTLE viene generato molto probabilmente. La soluzione potrebbe essere semplice come utilizzare Serializable invece. Maggiori informazioni qui http://nemanjakovacevic.net/blog/english/2015/03/24/yet-another-post-on-serializable-vs-parcelable/ –

+1

Penso che il suggerimento di Android di usare una classe Singleton per grandi dati temporanei sia un ottimo modo per andare. Mantiene la cosa semplice e veloce, con il pieno controllo di dove sono i tuoi dati. – mix3d

2

Se si passa un grande informazioni da uno a altra attività, allora può essere lo rendono App lento

ma utilizzare classe globale per memorizzare le variabili con l'utilizzo che si può facilmente ottenere o impostare valori

che ha dichiarato nel globale del file

vedere questo link:

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

+0

okay, questo è un workaraound su cui devo riflettere. Grazie mille! – sk2andy

+0

Non proprio un problema, ma penso che l'implementazione corretta: non si dovrebbero trasferire enormi blocchi di dati da un'attività all'altra. – Teovald

1

quanto ho ricordato, fino ad API-8 (Froyo), c'erano alcune limitazioni (come 1MB) quando passa attraverso oggetti Parcelable intenti. Tuttavia, puoi semplicemente annotare i tuoi dati parcelable in un file e inviare il percorso del file alla tua prossima attività tramite bundle. Successivamente, codifica la tua seconda attività per leggere i dati dal file ed eliminarli in seguito.

+0

forse, devi pensarci. Grazie! I riferimenti globali – sk2andy

+0

sono abbastanza allettanti ed è una scorciatoia, ma non è consigliabile per grandi quantità di dati. – waqaslam

+3

C'è ancora un limite oggi, in Lollipop, e può essere molto più piccolo di 1 MB. Ho scritto un post sul blog facendo luce sulla situazione http://nemanjakovacevic.net/blog/english/2015/03/24/yet-another-post-on-serializable-vs-parcelable/ –

0

Non ho idea del motivo per cui non funziona con i dati di grandi dimensioni, ma se non trovi alcun modo per risolverlo, ti suggerisco di utilizzare un'applicazione globale personalizzata, like here. (Controllare anche la risposta corretta per rendere funziona)

+0

ok, questo è possibile soluzione alternativa. Assumerò di farlo. Grazie mille! – sk2andy

23

Il modo in cui preferisco il passaggio di dati di grandi dimensioni è tramite l'utilizzo di enumerazioni. Alcuni vantaggi di questo approccio:

  • Non c'è bisogno di creare singleton, si ha sempre una singola istanza del proprio enum;
  • I dati sono incapsulati correttamente;
  • riferimento viene eliminato subito dopo l'attività riceve

Ecco un esempio:

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

Maggiori informazioni here.

+0

Ha funzionato per me! :) –

+0

apprezza la tua soluzione :) – Nisarg

+0

Questo usa la serializzazione enum? Com'è il rendimento rispetto all'approccio singleton? –