java - 我不能在 2 个 Activity 之间传递太大的对象数组列表?

标签 java android android-intent arraylist

我试图在 2 个 Activity 之间传递自定义对象的数组列表,但我收到了这个错误,我不知道如何解决它。如果有人能帮助我,我将不胜感激!提前致谢。

在第一个 Activity 中传递的方法:

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

get in 2's activity 中的方法:

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

错误日志:

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) 

最佳答案

提供的所有答案似乎质量都有些低。所以我再提供一个。

问题

您遇到的异常是由于您尝试通过 Bundle 传输的数据量太大造成的。

Note: I wrote a blog post about this topic on my website, it contains more detailed information. You can find it here: http://neotechsoftware.com/blog/android-intent-size-limit

解决方案

您无法通过标准方式(使用 Bundle 或 Parcel)转移您的对象,因为它太大了。在这些情况下经常使用两种解决方案:

  • 基于文件的临时存储和传输
  • 基于内存的存储和传输

基于文件

您可以将自定义对象数组存储在一个文件中,然后再读回。我不建议这样做,因为它通常比内存存储慢。然而,一种经常使用的技术是在适用的情况下使用某种数据库。然而,使用数据库有一个主要缺点,存储在数据库中的对象通常是临时对象,因此您需要在读取完它们后将其删除。如果出现问题,您的数据库可能会开始变得困惑。所以你需要一些干净的程序。避免这种情况的最佳方法可能是将数据库文件(或实际上用于此的任何文件)写入缓存目录。

内存中 1:(应用程序实例)

您最好的选择(并且可能是首选的 Android 方式)是将数组存储在 Application 实例中。为此,您需要创建一个类并使其扩展 Application。在此类中,您将创建一个公共(public)字段来写入和读取数组。

public class App extends Application {

    public ArrayList<YourObject> objects;

}

您可以通过获取Application实例来读写该字段。

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

不要忘记在 manifest.xml 文件中注册扩展的 Application 类! 为什么这样做:之所以可行,是因为 Application 实例不会在不同 Activity 之间销毁,它具有独立于 UI 的生命周期。

内存中 2(单例)

另一种选择是使用单例模式或创建一个带有静态字段的类。下面的示例演示了单例模式。

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;

Very important note on in-memory object storage: Assume that your app is in the background and you stored some object in the Application instance (or in a singleton container) to later restore it. If the Android system decides to kill your app because it needs to free some memory for another app, your objects will be destroyed. Now the important part, if the user returns to your app the Android system re-creates the destroyed Activity and passes a non-null "saved-instance-state" Bundle to the onCreate() method. You might assume at this point (because the Bundle is non-null) your in-memory stored objects exist, this is however not true! Conclusion: Always check if stored objects are non-null!

关于java - 我不能在 2 个 Activity 之间传递太大的对象数组列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34460827/

相关文章:

Android 查找已安装应用程序的 Intent

java - 我在 Android 中哪里可以得到这个 CoreSystemContext.SCALE

java - 如何确保hibernate提交了事务?

java - 将 cookie 从 JNLP 传递到 JAVAWS 以下载 protected 资源

android - Firebase Job Dispatches 不会触发我的服务类

android - AndEngine 如何在图片上放置文字?

android - 如何在不打开其他使用 "geo"方案的应用程序的情况下打开 Google map ?

java - Jersey - 来自 HTTP header 的编码(marshal)对象

java - Spring Openid、OpenIDAuthenticationToken

android.database.sqlite.SQLiteDatabase.rawQuery() 没有使用 SQLite datetime() 函数更新 DATETIME 列