2015-12-25 7 views
5

Ich versuche, Array-Liste von benutzerdefinierten Objekt zwischen 2 Aktivitäten Wurf Absicht übergeben, aber ich habe diesen Fehler und ich weiß nicht, wie man es löst. Ich werde es schätzen, wenn mir jemand helfen kann! Danke im Voraus.Ich kann nicht zu große Arraylist von Objekten zwischen 2 Aktivitäten übergeben?

Verfahren Pass in 1'st Aktivität:

i.putParcelableArrayListExtra("key", (ArrayList<? extends Parcelable>) result); 
startActivity(i); 

Methode in get in 2'st Aktivität:

Intent i = getIntent(); 
ArrayList<ItemObjects> list = i.getParcelableArrayListExtra("key"); 

Fehlerprotokoll:

12-25 09:11:49.546 17742-17742/com.example.baha.myapplication E/AndroidRuntime: FATAL EXCEPTION: main 
Process: com.example.baha.myapplication, PID: 17742 
java.lang.RuntimeException: Failure from system 
    at android.app.Instrumentation.execStartActivity(Instrumentation.java:1514) 
    at android.app.Activity.startActivityForResult(Activity.java:3917) 
    at android.app.Activity.startActivityForResult(Activity.java:3877) 
    at android.app.Activity.startActivity(Activity.java:4200) 
    at android.app.Activity.startActivity(Activity.java:4168) 
    at com.example.baha.myapplication.splash$GetMarkets.onPostExecute(splash.java:127) 
    at com.example.baha.myapplication.splash$GetMarkets.onPostExecute(splash.java:62) 
    at android.os.AsyncTask.finish(AsyncTask.java:651) 
    at android.os.AsyncTask.-wrap1(AsyncTask.java) 
    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:668) 
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:148) 
    at android.app.ActivityThread.main(ActivityThread.java:5417) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
Caused by: android.os.TransactionTooLargeException: data parcel size 12404332 bytes 
    at android.os.BinderProxy.transactNative(Native Method) 
    at android.os.BinderProxy.transact(Binder.java:503) 
    at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:2657) 
    at android.app.Instrumentation.execStartActivity(Instrumentation.java:1507) 
    at android.app.Activity.startActivityForResult(Activity.java:3917) 
    at android.app.Activity.startActivityForResult(Activity.java:3877) 
    at android.app.Activity.startActivity(Activity.java:4200) 
    at android.app.Activity.startActivity(Activity.java:4168) 
    at com.example.baha.myapplication.splash$GetMarkets.onPostExecute(splash.java:127) 
    at com.example.baha.myapplication.splash$GetMarkets.onPostExecute(splash.java:62) 
    at android.os.AsyncTask.finish(AsyncTask.java:651) 
    at android.os.AsyncTask.-wrap1(AsyncTask.java) 
    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:668) 
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:148) 
    at android.app.ActivityThread.main(ActivityThread.java:5417) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
+0

Wie groß ist dieses Array? –

+1

Besuchen Sie diesen Link kann es Ihnen helfen zu verstehen http://jyvee.com/passing-large-data-to-an-activity/ –

+0

welche Daten Sie zur nächsten Aktivität übergeben? Wenn es Bild ist dann verwenden Sie Bitmap –

Antwort

-1

Dies kann sehr oft passieren, wenn Sie Intent-Extras verwenden, um große Datenmengen zu übertragen.

Ihre Optionen:

  1. eine öffentliche Variable definieren, die von den anderen Klasse mit Variablen zugegriffen werden kann:

Sie Arrays haben würde, aber mein Beispiel hat Ints:

enter image description here

Jetzt möchten Sie auf diese Ints von einer anderen Klasse richtig zugreifen? Im Moment senden Sie den int zu der anderen Aktivität über die Absicht extra. Stattdessen können Sie ein Objekt von MyClass machen und sie auf diese Weise Zugang:

enter image description here

  1. Erstellen Sie eine gemeinsame Präferenzen Objekt mit der Arraydaten und Zugriff auf die Daten aus der andere Klasse.

    SharedPreferences prefs = this.getSharedPreferences ("com.example.app", Context.MODE_PRIVATE);

und bearbeiten:

prefs.edit().putInt(INT).apply(); 
+2

Nicht klar, wo diese MyClass selbst gespeichert wird. Das Schreiben von 1 MB Daten in eine gemeinsame Präferenz, die nur eine XML-Datei ist, ist ebenfalls problematisch. –

+0

@AlexanderKulyakhtin Eigentlich ist 'MyClass' die Klasse mit Ihrem Array. Erstellen Sie nun in Ihrer anderen Klasse ein Objekt von 'MyClass' und greifen Sie auf die Membervariable zu. Lass mich wissen ob es funktioniert! –

+0

@AlexanderKulyakhtin Großartig! Welche Methode hast du gewählt? –

-2

Sie können nicht, oder es lässt deine App einfrieren. Speichern Sie die Daten in Ihrem Application-abgeleiteten Objekt, so dass sie die ganze Zeit, die Sie benötigen, existieren.

+1

Das ist eigentlich eine bessere Antwort als die angenommene Antwort, obwohl die Menge der bereitgestellten Informationen könnte sei besser. –

+0

Was ist los mit meiner Antwort? –

+0

Nichts. Fügen Sie einfach weitere Details hinzu;) –

-2

Sie können nicht zu großes Objekt mit Absicht übergeben.Wenn Sie zur Verwendung dieser Daten in mehr als einer Aktivität möchten, können Sie eine Hilfsklasse wie folgt definieren:

public class MyData { 
    private static MyData sInstance = new MyData(); 
    public static MyData get() { return sIntance; } 

    private ArrayList<> data; 
    public List<> getData() { return data; } 
    public void loadData() { 
     // load data 
    } 
} 

Sie Daten in einer Aktivität laden kann, dann, wenn Sie auf eine andere Tätigkeit zu springen, können Sie einfach :

ArrayList<> data = MyData.get().getData(); 
4

Alle Antworten scheinen ein wenig niedrige Qualität. Also werde ich einen anderen zur Verfügung stellen.

Das Problem

Die Ausnahme Sie wird verursacht durch die Tatsache erhalten, dass die Menge an Daten, die Sie durch ein Bündel übertragen möchten, ist einfach zu groß.

Hinweis: Ich schrieb eine Blog-Post zu diesem Thema auf meiner Website, es detailliertere Informationen enthält. Sie können es finden Sie hier: http://neotechsoftware.com/blog/android-intent-size-limit

Lösungen

Es gibt keine Möglichkeit, Sie übertragen können, wird Ihnen Objekt durch die Standardmethode sind (ein Bundle oder Paket verwendet wird), weil es einfach zu groß. Es gibt zwei Lösungen, die häufig in diesen Fällen verwendet werden:

  • Datei-basierte temporäre Speicherung und Übertragung
  • In-Memory-basierte Speicherung und Übertragung

Datei-basierte

Sie könnten Speichern Sie das Array von benutzerdefinierten Objekten in einer Datei und lesen Sie es später zurück. Ich empfehle das nicht, da es im Allgemeinen langsamer ist als In-Memory-Speicher. Eine häufig verwendete Technik besteht jedoch darin, eine Datenbank in irgendeiner Form zu verwenden. Die Verwendung einer Datenbank hat jedoch den großen Nachteil, dass Objekte, die in der Datenbank gespeichert sind, oft temporäre Objekte sind, so dass Sie sie nach dem Lesen entfernen müssen. Wenn etwas schief geht, fängt Ihre Datenbank an, Unordnung zu enthalten. Du brauchst also eine saubere Routine. Die beste Methode, dies zu vermeiden, ist wahrscheinlich, die Datenbankdatei (oder tatsächlich jede Datei, die dafür verwendet wird) in ein Cache-Verzeichnis zu schreiben.

In-Memory-1: (Anwendungsinstanz)

Ihre beste Möglichkeit (und wahrscheinlich die bevorzugte Art und Weise Android) ist das Array in der Application Instanz zu speichern. Um dies zu tun, müssten Sie eine Klasse erstellen und sie erweitern Application. In dieser Klasse erstellen Sie ein öffentliches Feld zum Schreiben und Lesen des Arrays.

public class App extends Application { 

    public ArrayList<YourObject> objects; 

} 

Sie können durch Erhalten der Application Instanz auf dieses Feld lesen und schreiben.

App app = (App) getApplicationContext(); 
app.objects = yourArrayList; 

Vergessen Sie nicht Ihren erweiterten Application Klasse in der manifest.xml-Datei zu registrieren!Warum funktioniert das? Das funktioniert, weil die Application Instanz zwischen den verschiedenen Aktivitäten nicht zerstört wird. Sie hat einen von der Benutzeroberfläche unabhängigen Lebenszyklus.

In-Memory 2 (Singleton)

Eine weitere Option ist das Singleton Muster zu verwenden oder eine Klasse mit statischen Feldern erstellen. Das folgende Beispiel demonstriert das Singleton-Muster.

public class DataContainer { 

    private static DataContainer instance = null; 

    public static DataContainer getInstance(){ 
     /** 
     * Synchronizing this method is not needed if you only use it in 
     * Activity life-cycle methods, like onCreate(). But if you use 
     * the singleton outside the UI-thread you must synchronize this 
     * method (preferably using the Double-checked locking pattern). 
     */ 
     return instance != null?instance: (instance = new DataContainer()); 
    } 

    public ArrayList<YourObject> objects; 

} 


DataContainer.getInstance().objects = yourArray; 

Sehr wichtiger Hinweis auf In-Memory-Objektspeicher: Angenommen, Ihre Anwendung im Hintergrund ist und Sie einen Gegenstand in der Application Instanz (oder in einem Singleton-Containern) gespeichert, um es später wieder herstellen. Wenn das Android-System entscheidet, Ihre App zu beenden, weil es Speicherplatz für eine andere App freigeben muss, werden Ihre Objekte zerstört. Jetzt der wichtige Teil, wenn der Benutzer zu Ihrer App zurückkehrt das Android-System neu erstellt die zerstörten Activity und übergibt einen Nicht-Null "saved-instance-state" Bundle an die onCreate() Methode. Sie könnten an dieser Stelle annehmen (weil Bundle nicht null ist), dass Ihre im Speicher gespeicherten Objekte existieren, dies ist jedoch nicht wahr! Fazit: Überprüfen Sie immer, ob die gespeicherten Objekte nicht null sind!

Verwandte Themen