我不能在两个活动之间传递太大的对象arraylist?

Dev*_* HH 5 java android arraylist android-intent

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

传递第1个活动的方法:

i.putParcelableArrayListExtra("key", (ArrayList<? extends Parcelable>) result);
startActivity(i);
Run Code Online (Sandbox Code Playgroud)

进入第2个活动的方法:

Intent i = getIntent();
ArrayList<ItemObjects> list = i.getParcelableArrayListExtra("key");
Run Code Online (Sandbox Code Playgroud)

错误日志:

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) 
Run Code Online (Sandbox Code Playgroud)

Rol*_*f ツ 7

提供的所有答案似乎都有点低质量。所以我会提供另一个。

问题

您得到的异常是由于您尝试通过 Bundle 传输的数据量太大这一事实造成的。

注意:我在我的网站上写了一篇关于此主题的博客文章,其中包含更详细的信息。你可以在这里找到它:http : //neotechsoftware.com/blog/android-intent-size-limit

解决方案

您无法通过标准方式(使用捆绑包或包裹)传输您的对象,因为它实在是太大了。在这些情况下,通常使用两种解决方案:

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

基于文件

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

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

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

public class App extends Application {

    public ArrayList<YourObject> objects;

}
Run Code Online (Sandbox Code Playgroud)

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

App app = (App) getApplicationContext();
app.objects = yourArrayList;
Run Code Online (Sandbox Code Playgroud)

不要忘记Applicationmanifest.xml文件中注册您的扩展类!为什么这样工作:这是有效的,因为Application实例不会在不同的活动之间被破坏,它有一个独立于 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;
Run Code Online (Sandbox Code Playgroud)

关于内存中对象存储的非常重要的说明:假设您的应用程序在后台,并且您在Application实例(或单例容器)中存储了一些对象,以便稍后恢复它。如果 Android 系统决定终止您的应用程序,因为它需要为另一个应用程序释放一些内存,那么您的对象将被销毁。现在重要的部分是,如果用户返回到您的应用程序,Android 系统会重新创建被销毁的对象Activity并将非空的“保存实例状态”Bundle传递给该onCreate()方法。此时您可能会假设(因为Bundle非空)您的内存中存储的对象存在,但事实并非如此!结论:始终检查存储的对象是否为非空!


Ruc*_*nia 0

当使用 Intent Extras 传递大量数据时,这种情况经常发生。

您的选择:

  1. 定义一个可以使用变量从其他类访问的公共变量:

你会有数组,但我的例子有整数:

在此输入图像描述

现在,您想从另一个类访问这些整数,对吗?现在,您正在通过 Intent extra 将 int 发送到其他活动。相反,您可以创建一个对象MyClass并以这种方式访问​​它们:

在此输入图像描述

  1. 使用数组数据创建一个共享首选项对象,并从其他类访问数据。

    SharedPreferences 首选项 = this.getSharedPreferences("com.example.app", Context.MODE_PRIVATE);

并编辑:

prefs.edit().putInt(INT).apply();
Run Code Online (Sandbox Code Playgroud)

  • 不清楚 MyClass 本身将存储在哪里。将 1 MB 数据写入共享首选项(只是一个 xml 文件)也是有问题的。 (2认同)