最近在翻看项目里面一些老的业务模块的时候,发现不少Activity里面建立Fragment的地方都照搬了网上流传的错误的作法,习惯性地在扩展Fragment类中写一个newInstance(T parmas)的静态函数,而后在Activity中经过调用该函数建立所需的Fragment实例 并把须要的数据做为参数从Activity传入到Fragment中:bash
诚然这使咱们能够很方便地获取到Fragment的实例,可是因为参数使经过静态函数传入的,没法直接赋值给Fragment实例的内部 变量,而是经过setArguments()的方式保存在Fragment类特殊持有的Bundle中,待须要时再将其取出来使用。问题由此引起而来,若是传递的参数是几个基本数据类型或者比较简单的类,那么不会产生任何问题,当传递的数据量比较大的时候(好比说数量可观的List)容易产生内存问题。由于Bundle只接受基本数据类型或者已实现了Serializable序列化接口的类型,因此当咱们把数据序列化后 在传递进去,实际上序列化自己是一个深拷贝的过程,此时内存中已经产生了数据的一个副本,而不是对该数据的引用,形成了内存的浪费。当一个Activity中包含有不少这样的Fragment的时候产生的问题更大:
当app转到后台以后,fragment状态变量会经过activity的onSaveInstanceState()函数保存,查看源码可看到底层经过Parcel进行传递,而Parcel的传递的大小是有限制的,通常为1Mb左右,若是超出了限制应用甚至会崩溃掉。因此对于Activity和Fragments之间大数据量的传递应该使用浅拷贝的机制,即在内存中应该只存在一个实例,Activity和Fragment只对其进行引用。运用Android Jetpack架构里面的 ViewModel能够很容易地实现上面这一点。
public void loadPageDetailFinish(TabListBean pageInfo) {
PageViewModel model = ViewModelProviders.of(this).get(PageViewModel.class);
model.setPageInfo(pageInfo);
}
复制代码