Activity和Fragments之间的参数传递和内存优化

676 阅读2分钟

最近在翻看项目里面一些老的业务模块的时候,发现很多Activity里面创建Fragment的地方都照搬了网上流传的错误的做法,习惯性地在扩展Fragment类中写一个newInstance(T parmas)的静态函数,然后在Activity中通过调用该函数创建所需的Fragment实例 并把需要的数据作为参数从Activity传入到Fragment中:

诚然这使我们可以很方便地获取到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);
    }