集成 React Native 到现有Android项目(二)

上篇文章讲解了ReactNative的官方引入方式,官方方式不一定全部合适大家的项目应用。

这篇主要解说,引入跨平台后,我们的App带来了哪些大问题,而针对这些问题我们是怎么处理的 ,有哪些成果。

初始集成基于reactnative:0.55.2

跨平台方案在APP迭代过程中的一些主要问题

  • ReactNative搭配native公共组件,交融与交互?
  • ReactNative页面首次打开,速度不够快?
  • ReactNative使用导致内存飚升,OOM概率大大提升?

一、商品详情如何使用ReactNative+Native?

思考: 初始 App使用Web+Native的方式实现商品详情的,痛点:打开商品慢。ReactNative官方只提供了activity级别的加载功能,想要相对低成本和可扩展性的方式,引入ReactNative替换,那必须探索将ReactNative支持更小单元的组件化,达到至少类Webview元素接近。

难点:商品详情支持重复打开,

剖析RN提供的ReactActivity.class页面加载源码,得到RN通过ReactNativeHost实现ReactInstanceManager加载页面和管理页面的生命周期。

//ReactActivity.class--->ReactDelegate.class
//加载RN页面的主要代码
  public void loadApp(String appKey) {
    if (mReactRootView != null) {
      throw new IllegalStateException("Cannot loadApp while app is already running.");
    }
    mReactRootView = createRootView();
    mReactRootView.startReactApplication(
        getReactNativeHost().getReactInstanceManager(), appKey, mLaunchOptions);
  }
//RN核心,Bridge引擎
public ReactInstanceManager getReactInstanceManager() {
    return getReactNativeHost().getReactInstanceManager();
  }

得到结论后,通过重写ReactNativeHost,创建了类似ReactActivity的RNFragment的小单元容器类,这样就很便捷了的解决reactnative引入项目的方式

ps:RN后续高版本,官网有采取一些issue,提供类似的ReactFragment容器类,但是了解加载原理,对自己自定义容器类很有必要,你有可能需要更进一步改造容器类。

二、引入ReactNative后,内存飚升,OOM概率大大提升?

**思考:**引入App项目后,商品详情打开商品详情无限重开,导致部分手机,打开6个左右商品详情页面就会引发OOM崩溃。在第一阶段对ReactNative容器进行了自定义,故针对这个情况我们第一时间通过栈方式,管理回收商品详情页面,让商品详情最多保持3个页面。

后续迭代中,商品详情不断的壮大,其他问题也导致了oom

开始引入后,参考京东&天猫,我们通过栈回收,解决了第一个OOM问题。

//不断改造的栈回收方式
public class RNStack extends Stack<ReactRootView> {
    /**
     * DES:   处理RN系统预留内存峰值进行页面层级管理
     * TIME: 2018/12/17 0017 下午 2:20
     */
    @Override
    public synchronized boolean add(ReactRootView reactRootView) {
        try {
            return super.add(reactRootView);
        } finally {
            //RN 预留内存峰值
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                gcRnStack4Num(3);
            } else {
                gcRnStack4Num(2);
            }
        }
    }
    public boolean remove(ReactRootView reactRootView) {
        reactRootView.unmountReactApplication();
        return super.remove(reactRootView);
    }
    /**
     * DES:  num  表示可以保持的栈数量
     * TIME: 2019/3/20 0020 下午 4:45
     */
    private void gcRnStack4Num(int num) {
        if (size() > num) {
            ReactRootView rootView = firstElement();
            if (rootView != null) {
                Context context = rootView.getContext();
                if (context instanceof Activity) {
                    ((Activity) context).finish();
                }
                remove(rootView);
            }
        }
        System.gc();
        System.runFinalization();
    }
}

后迭代中,商品详情不断的壮大,每个商品都引入了大几百的推荐商品列表,部分手机可见大部分推荐商品后,在第二个或者第三个商品详情又引发了OOM异常。后面通过RN页面修改加载逻辑,实现不可见回收方式解决的。

ps:这种情况,进过测试验证,发现Native中RN回收的速度比较慢,所以通过Native手段未未解决这种OOM

三、ReactNative页面首次打开速度不够快

思考: 使用一段时间后,商品详情RN页面,对比Web版本的详情打开已经很快了,但是对比同行的App,页面首次打开速度可以再度提速的

页面加载源码&测试验证发现,耗时地方主要在初始化引擎&加载RN bundle模块地方,且初始RN引擎&渲染加载可以分开。于是前期我们就做了,以空间换时间的概念提速,在启动app时,提前初始化。

//预加载方案
Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {
            @Override
            public boolean queueIdle() {
                final ReactInstanceManager rim = getReactInstanceManager(application);
                if (!rim.hasStartedCreatingInitialContext()) {
                    rim.addReactInstanceEventListener(new ReactInstanceManager.ReactInstanceEventListener() {
                        @Override
                        public void onReactContextInitialized(ReactContext context) {
                            // 初始化react上下文时调用(所有模块都已注册)。 总是调用UI线程。
                            rim.removeReactInstanceEventListener(this);
                        }
                    });
                    rim.createReactContextInBackground();
                }
                return false;
            }
        });

ps:后续参考了携程开源的CRN,他们也是通过这种方式提升加载速度的

优化后,我们的商品详情在中等手机上,首次打开提速了5倍,非首次没有变化,这是当时的测试结果

版本号第一次第二次第三次
3.68.081511196ms536ms502ms
3.68.081337528ms530ms535ms

ps:后续我们也再次进行了Bundle分包加载,提高 200ms左右的加载速度,没有第一次提速那么显著。

但是内存换速度也不是完美无瑕的,在我们app也引发了一些副作用

  • App启动初始化东西太多,一次性占用太多内存,会导致某些手机,ANR几率比较高 (可以对部分机型取是否预加载做取舍)

总结

在对待新事物时,我们可以剖析源码或者参考同类开源方案,这样就可以最快最优得到解决方案。

跨平台方案一直是各大电商平台积极拥抱的,其比Native在实时更新方面更能满足业务需求。

ReactNative在引入App后,我们对其进行了各种适配支持,来满足业务需求,提高用户体验和交付速度,但其存在在一定程度上对app整体的健壮性与稳定性产生了负作用,需要任重道远继续探索与优化。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值