Intent.putExtras 大小有限制吗?

发布于 2025-01-07 09:55:34 字数 1068 浏览 1 评论 0原文

我试图通过 Intent.putExtras 将数据从一个活动传递到另一个活动,如下所示:

private ArrayList<HashMap<String, String>> mGroups = new ArrayList<HashMap<String, String>>();
private ArrayList<HashMap<String, String>> mUsers = new ArrayList<HashMap<String, String>>();
...

Bundle data = new Bundle();
data.putInt("mode", mode);
data.putSerializable("groups", (Serializable) mGroups);
data.putSerializable("users", (Serializable) mUsers);
data.putInt("current_class", mCurrentClassId);
data.putInt("current_user", mCurrentUserId);

Intent intent = new Intent(ctx, ChildActivity.class);
intent.putExtras(data);
ctx.startActivityForResult(intent, 0);

这里 mUsersHashMap 的列表code> 包含用户数据,包括 Base64 编码的照片,此列表中的字符串大小总和约为 500Kb

startActivityForResult 的调用在黑屏下挂起几分钟,然后我得到ANR 错误。子Activity的onCreate根本没有被调用。

如果我不将大字符串添加到 mUsers 中(没有 Base64 编码的照片) - 工作得很好。

请帮忙。

I'm trying to pass data from one activity to another via Intent.putExtras like this:

private ArrayList<HashMap<String, String>> mGroups = new ArrayList<HashMap<String, String>>();
private ArrayList<HashMap<String, String>> mUsers = new ArrayList<HashMap<String, String>>();
...

Bundle data = new Bundle();
data.putInt("mode", mode);
data.putSerializable("groups", (Serializable) mGroups);
data.putSerializable("users", (Serializable) mUsers);
data.putInt("current_class", mCurrentClassId);
data.putInt("current_user", mCurrentUserId);

Intent intent = new Intent(ctx, ChildActivity.class);
intent.putExtras(data);
ctx.startActivityForResult(intent, 0);

Here mUsers is a List of HashMap<String,String> with users' data, including Base64-encoded photo, sum of strings sizes in this list is about 500Kb

Call to startActivityForResult hangs for several minutes with black screen and then I get ANR error. Sub-Activity's onCreate is not called at all.

If I don't add large strings into mUsers (no Base64-encoded photos) - works just fine.

Please help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

德意的啸 2025-01-14 09:55:34

如果这两项活动都是您的,请使用合适的数据模型。 Android 并不鼓励设计精良的应用程序。或者换个角度来看,它允许快速开发应用程序,并且不会促进太多良好的软件应用程序原则。

@Jean-Philippe Roy(魁北克?)的解决方案很有趣,但当涉及到更复杂的事物(即有状态模型或 serviceS)时,单例是一种相当反模式。

最好的选择是使用应用程序类。这个类本质上是 Android 中的单例。因此,

  • 在清单中定义一个应用程序类,
  • 提供一个静态方法来访问应用程序类的唯一实例(它始终是单例)。
  • 给它一个方法来接收和保存您的数据,从您的第一个活动
  • 和第二个活动中调用它,以便将它们返回到您的第二个活动中

---在 @straya 的回答和 18 个多月的 Android 编程之后更新:)

共享的问题在构建 Android 应用程序时,始终会考虑跨应用程序、活动、视图、片段的数据结构或流程。重要的是要了解并考虑应用程序范围是保存共享结构的正确位置,但是使用应用程序类本身将数据结构放入该范围内是不可行的:

  • 代码质量,如果所有共享数据结构和进程如果了解该应用程序,它很快就会因所有这些实体的访问器而变得臃肿。
  • 只有一个实体的全局共享池,它的粒度不够,可能导致难以检测耦合实体的方式,

我现在倾向于使用依赖注入管理的单例。 Dagger 或 RoboGuice 都允许创建给定类的单个实例并将其注入到其他类中。这种技术以及更普遍的 DI 为良好的 Android 设计提供了巨大的可能性:

  • 不会降低代码质量,甚至可以大大缩短代码的质量。使用@Inject来注入依赖项,它们就会被注入。
  • 不要给单例类赋予 2 个职责:它不会处理单例实例的创建,框架会处理它。
  • 从单例传递到普通实例更容易,
  • 因为这些单例成为带有简单注释的普通类,它们不再包含静态方法,这允许非常容易地模拟它们。这是很重要的一点。
  • 当然,当一个类依赖于另一个类时,DI 注释可以非常清楚地表明,有助于更多地自我记录代码。

if both activities are yours, use a decent data model. Android doesn't encourage that much to very well designed application. Or turn it differently, it allows for fast developped application and doesn't promote much of good software application principle.

The solution of @Jean-Philippe Roy (québec ?) is interesting but singleton are quite an anti-pattern when it comes to more elaborate things, namely statefull models or serviceS.

The best option is to use an application class. This class is your singleton, by nature in android. So,

  • define an application class in your manifest
  • provide a static method to access the unique instance of the application class (it is always a singleton).
  • give it a method to receive and hold your data, call it from your first activity
  • and a second one to get them back in your second activity

---Updated after @straya's answer and 18 more month of Android programming :)

The question of sharing a data structure or processes accross application, activities, views, fragments is always present at mind when building Android application. It's important to know and consider that the application scope is the right place to hold shared structure, but using the application class itself to put a data structure in that scope is not viable with regards to :

  • code quality, if all shared data structures and process are know of the application, it will quickly become bloated with accessors for all those entities.
  • there is only one global shared pool of entities, which is not find grained enough and may lead to hard to detect ways of coupling entities

I now tend to prefer using Dependency Injection managed singletons. Dagger or RoboGuice both allow to create and inject a single instance of a given class into other classes. This technique, and DI more generally offers great possibilities for good Android designs :

  • don't degrade quality of code, it is even shortened quite a lot. Use @Inject to inject dependencies and they will get injected.
  • don't give 2 responsibilities to the singletoned class : it will not handle the singleton instance creation, the framework will do it.
  • it's easier to pass from a singleton to a normal instance
  • as those singletons become normal classes with a simple annotation, they do not contain static methods anymore and this allows to mock them very easily. And that's a big point.
  • and of course, DI annotations make it very clear when a class depends on another class, helping to self document code more.
浅沫记忆 2025-01-14 09:55:34

进程级别,最大大小为1MB,而不是在捆绑包级别。这 1MB 用于应用程序进程中正在进行的所有状态事务(例如 onSaveInstanceState、startActivity 等)使用的共享缓冲区。

在 Android 7.0(API 级别 24)及更高版本上,当达到此进程级别限制时,系统会抛出 TransactionTooLargeException。在旧版本上,您只会收到警告。

正如其他人所建议的,如果您需要传递更大的有效负载,您应该研究替代方案,例如使用本地数据库、文件系统、应用程序级内存缓存、远程存储、共享首选项(尽管这些也需要很小)等。

事实来源: https://developer.android.com/guide/components/activities/parcelables-and-bundles

Maximum size is 1MB at Process Level, not at bundle level. This 1MB is for a shared buffer used by all state transactions in progress in the app's process, e.g. onSaveInstanceState, startActivity and others.

On Android 7.0 (API level 24) and higher, the system throws a TransactionTooLargeException when this process level limit is reached. On older versions you only get a warning.

As others suggested, you should research alternatives, if you need to pass a larger payload, e.g. use local database, file system, application level in-memory cache, remote storage, shared preferences (although these need to be small too), etc.

Source of truth: https://developer.android.com/guide/components/activities/parcelables-and-bundles

扎心 2025-01-14 09:55:34

只是为了回应 Snicolas 的回答:

应用程序已经是单例,无需将其“变成”单例。

就我个人而言,在长期严重依赖应用程序来保存数据之后,我开始不再完全信任它。不过,我使用自缓存数据对象来缓解问题;)

Just in response to Snicolas' answer:

Application is already a Singleton, no need to "turn it to" one.

Personally, after some serious reliance on Application to hold data for a long time, I've come to not trust it entirely. I use self-caching data objects to mitigate the problems though ;)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文