微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

react-native优化--压缩apk安装包大小

一个简单的react-native HelloWorld项目打包后的大小是7MB多,对于现有项目集成react-native来说是一个不小的负担。而拆开apk包占据大部分容量的是react-native的so,所以我们的法子是怎么减少打包的so。本文讲的方法对于很多只是在现有项目中集成react-native做部分业务模块实验目的用户来说是肥肠有用的。

废话少说先来一个压缩so惯用的伎俩:

只保留armeabi so

大家惯用的伎俩了,不多解释直接上个删除其他abi的gradle代码方便大家

splits {
    abi {
        enable true
        reset()
        include 'armeabi'
    }
}


react-native so不打包进apk,而是从网络下载

react-native能运行的api level需要>=16,意味着android 4.1以下系统是跑不了react-native的。对于android 4.1以下系统那么干脆禁掉react-native独立打包或许是个不错的选择。但是你能独立对android 4.1以下系统独立打包,用户不会乖乖下载指定系统的安装包的。所以我在这里提出一个更加彻底的方案:所有react-native的so都不打包进apk,而是在用户启动后下载react-native的so再放置到lib目录。

将react-native做成动态下载so,面临的一个技术问题是程序安装包的lib目录没有写入权限的。所以我们得想法子让react-native从其他目录加载so而不是从认的so目录。幸运的是reac-native是用SoLoader库来加载so。我们可以从SoLoader入手对SoLoader代码修改或者是hack让它从指定的目录加载react-native的so。先来看看SoLoader在react-native中的初始化流程

由ReactInstanceManager.Builder创建ReactInstanceManager(XReactInstanceManagerImpl/ReactInstanceManagerImpl),XReactInstanceManagerImpl(ReactInstanceManagerImpl)调用SoLoader.init初始化一些SoSource存储在静态数组sSoSources中。

SoSource是一个抽象类,负责处理你想要怎么加载so。该类需要实现两个方法

public int loadLibrary(String soName,int loadFlags)

加载so相当于System.loadLibrary

public File unpackLibrary(String soName)

确保so已经加压存到对应的目录

除了NoopSoSource其他SoSorce子类都是继承自DirectorySoSource,让我们来看看SoSorce的实现类DirectorySoSource。DirectorySoSource的loadLibrary实际调用的是loadLibraryFrom,一个protected方法

int loadLibraryFrom(String soName,int loadFlags,File libDir)

loadLibraryFrom的参数libDir可以传入加载so的路径.

到这里您应该明白更改SoLoader加载so路径的方法了吧:写一个DirectorySoSource代理类替换掉DirectorySoSource(修改SoLoader的静态变量sSoSources),在loadLibrary、unpackLibrary时发现是react-native的so,设法让它跑到指定的目录加载。

最后,代码就不上了。方法2中简单的反射一下或者修改SoLoader代码都是可行的。通过这两个方法处理后最后打包一个HelloWorld项目立马减少5MB多

原文地址:https://www.jb51.cc/react/305439.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐