当前位置: 首页 > 知识库问答 >
问题:

碎片newInstance保存到捆绑包的数据过多-Android.os.TransactionToolargeException

彭礼骞
2023-03-14

我已经创建了碎片标准方式(Android工作室生成的骨架)。所以我有newInstance静态方法:

public static EventsMapFragment newInstance(List<Event> eventList, String accessToken, String tokenType, String cityId, boolean isMessage)
{
     Bundle args = new Bundle();
     args.putString("events", new Gson().toJson(eventList));
     EventsMapFragment fragment = new EventsMapFragment();

     ///...........
     fragment.setArguments(args);
     return fragment;
}

然后,在oncreateoverride中,我需要检索我的集合,非常标准的方式:

 @Override
 public void onCreate(Bundle savedInstanceState)
 {
    super.onCreate(savedInstanceState);
    if (getArguments() != null)
    {
        String json = getArguments().getString("events");
        Type type = new TypeToken<List<Event>>(){}.getType();
        mEventList = new Gson().fromJson(json, type);
   }

问题是eventlist集合非常大,因此我得到了异常:

java.lang.RuntimeException:Android.os.TransactionToolargeException:数据包大小592196字节

在我的应用程序中的其他地方(奇怪的是,json被正确地传递,但是系统不允许传递更多的东西到bundle,跟踪问题的确切位置并不容易)。

因为newInstance()方法是静态的,所以我无法创建retain fragment并将数据传递到它中(在这种情况下,我实际上不知道如何做到这一点)。

我的解决方案是使用weakReference来传递数据,类似于:

public class DataHolder
{
    private static final DataHolder holder = new DataHolder();
    Map<String, WeakReference<Object>> data = new HashMap<>();

    public static DataHolder getInstance() {return holder;}

    public void save(String id, Object object)
    {
        data.put(id, new WeakReference<>(object));
    }

    public Object retrieve(String id)
    {
        WeakReference<Object> objectWeakReference = data.get(id);
        return objectWeakReference.get();
    }
}

然后,要存储数据(而不是使用bundle):

DataHolder.getInstance().save("eventList", eventList);

并检索数据:

mEventList = (List<Event>) DataHolder.getInstance().retrieve("eventList");

但是,这在KitKat上不起作用(在5.1和更新版本上似乎可以很好地工作)。主要问题我无法在KitKat上调试,因为multidex,所以调试编译甚至无法在KitKat上运行(发行版有minifyEnabled=true并且没有multidex)。但在KitKat上,似乎是这样的:

mEventList = (List<Event>) DataHolder.getInstance().retrieve("eventList");

始终为空。

你有什么想法吗?我目前的解决方案是检查构建版本并将json传递到KitKat上的bundle(它在KitKat上工作,问题是7.0及更新版本),并在更新的Android版本上使用WeakReference。

但实际上我对此并不满意。

[编辑]所以我的最后一次尝试是从父级activity获取事件集合。在主activity,我有以下代码(一个应用程序抽屉菜单点击):

if (menuId == R.id.nav_events_map)
{
  eventsToDraw =  Lists.newArrayList(Collections2.filter(events,x->!Utils.isGeojsonEmpty(x.getGeojson())));
  //....................
  if(eventsToDraw.size() >0)
  {
    mFragment = EventsMapFragment.newInstance();
    ReplaceFragment(mFragment);
  }
  else
  {
   mFragment = NoDataFragment.newInstance(getString(R.string.message_no_events));
   ReplaceFragment(mFragment);
 }
}

EventStoDraw是私有字段,我只是创建了getter:

public List<Event> getEventsToDraw()
{
  return eventsToDraw;
}

然后,在我的地图片段内部:

@Override
 public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
 {
  //Map initialization stuff
  //....................

   mEventList = ((MainActivity)getActivity()).getEventsToDraw();

  //Draw on map stuff etc
 }

问题是我总是得到meventlistnull。经过一些调试,我注意到getEventStoDraw()被调用为early,因此它不会返回我的集合,它返回null,因为还没有可用的数据。

共有1个答案

蒋飞捷
2023-03-14

它在KitKat上起作用

不,不是。1MB的IPC事务限制已经存在了很多年。但是,该限制只适用于您的流程的所有同时IPC事务,因此失败将是概率性的。例如,592196不到1MB,因此,为您崩溃的东西有时可能会通过OK,因为碰巧在那一刻与IPC发生的其他事情很少。

所以我有newInstance静态方法

不要传递事件集合。传递片段获取事件集合所需的最起码的信息。使用流程级POJO缓存来最大限度地减少冗余I/O,但如果需要,支持再次访问数据库/网络/任何内容,因此您可以处理配置更改(流程缓存仍然存在)和流程终止(但用户返回任务的速度相当快,因此仍然使用实例stat)。

 类似资料:
  • 我对kotlin相对较新,并试图在一些片段中构建一个带有数据绑定的项目。我有一个名为UserFraank的片段,其中包含一个Recyclview,如下所示: 以及用户的xml布局文件片段。xml如下所示: 还有一个类似的适配器类和item_user.xml: item-user.xml: 请注意,gradle中已经启用了数据绑定,这里非常重要的问题是,在我的片段和适配器中,这一行: 报告类型不匹配

  • 我有一个包含多个按钮的活动,当单击一个按钮时,将打开一个包含两个片段的新活动。 我试图根据按下的按钮在其中一个片段中显示一个回收器视图。问题是捆绑包为空,所以回收器视图不显示。 捆绑包在<code>onAttach 碎片 公共类MyFragment扩展片段{

  • 问题内容: 命令: 异常(来自日志文件) 但是以下jar可用。 关于上述错误有什么建议吗? 问题答案: 您需要安装几个捆绑软件才能使用控制台,如果仅使用Equinox启动,则您将不会获得这些捆绑软件。 使此工作最快的方法是创建一个具有以下内容的文件: 注意, 您将不得不根据实际拥有的版本检查这些捆绑软件的版本号。我使用SDK-4.2M6进行了尝试,其中某些可能已在RC3中更改。

  • 我有两个虚拟机在Openstack上运行。我在交换机中分配了一个数据网络网关,MTU=1500,其中VMs必须运行。 同样在OpenStack中,我设置了网络的默认MTU=1500。 我试图ping从VM到网关(或同一网络上的任何IP)的交换机与1500封装大小,它的去碎片分组。 相反,如果我用更小的mtu(1472)发送数据包,它会工作, 我能看到28个字节的差异,我不明白,这28个字节在哪里被

  • 我知道这个答案:Pax考试:提供具有所有依赖项的捆绑包,但当我必须包含作为我项目外部捆绑包一部分的捆绑包时,感觉我做错了什么。 这是我得到的错误: 下面是我的pax考试的配置代码: 所以我的问题是:为什么我会遇到关于未解决约束的错误,我是否必须包括外部捆绑包,以及我需要做什么才能让我的测试运行?

  • 我有3个片段(片段Home、片段A、片段B和片段C)。应用程序首次运行时将显示片段主页(在Mainactivity中设置)。从导航绘图项可以选择每个片段。每个选定项目都将显示详细信息片段。 我在处理数据和保留片段时遇到问题: (1)。当我选择一个片段(例如片段a)时,将显示片段a的页面。但是当我旋转设备时,为什么我的片段返回到片段主页而不是停留在当前片段??如何处理 (2)。在片段B中,我在Gri