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)
提供的所有答案似乎都有点低质量。所以我会提供另一个。
问题
您得到的异常是由于您尝试通过 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)
不要忘记Application在manifest.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非空)您的内存中存储的对象存在,但事实并非如此!结论:始终检查存储的对象是否为非空!
当使用 Intent Extras 传递大量数据时,这种情况经常发生。
您的选择:
你会有数组,但我的例子有整数:
现在,您想从另一个类访问这些整数,对吗?现在,您正在通过 Intent extra 将 int 发送到其他活动。相反,您可以创建一个对象MyClass并以这种方式访问它们:
使用数组数据创建一个共享首选项对象,并从其他类访问数据。
SharedPreferences 首选项 = this.getSharedPreferences("com.example.app", Context.MODE_PRIVATE);
并编辑:
prefs.edit().putInt(INT).apply();
Run Code Online (Sandbox Code Playgroud)