文安县建仓机械厂

陕西塑料挤出机设备 小记一个ReactNative Android上的设计实现缺陷导致界面卡死的问题 - Lrdcq - 驴肉の空间

发布日期:2026-01-14 21:29点击次数:66

塑料挤出机 在ReactNative使用过程中,我们遇到一个特殊动作下Android端RN页面直接卡死的场景,本文记录该卡死的排查过程与原理分析。问题现象假设我有一个RN页A,可以重复打开。我的操作是,root界面,打开A,再打开了其他界面X到Y到Z的业务链条。执行一定操作后,会触发回到root界面即clear top打开root界面,同时再次打开A,来实现快速回到A并刷A。这里不直接clear top到A的原因是,root界面和root界面打开A或者其他MN页面,都可以触发XYZ流程,并且在流程结束后,都期望回到root+A的页面状态,因此XYZ流程结束流程指定为“回到root界面即clear top打开root界面,同时再次打开A”。假设一开始打开的A叫RN-A,第二次打开的A叫RN-B,那整个路径上页面栈的改变类似于:680) {this.resized=true; this.width=680;}">背景如上,但是这个操作后打开的A,我们这里叫A一撇或者叫B吧,会卡死,页面事件可以响应但是很多桥触发不了,页面也无法返回包括物理返回,js异常也不会触发红屏了。更离谱的是,一旦我home到桌面再回来,一切就恢复了。关注到部分桥与调用行为在异常过程中报错“Activity is null!”,即可开始断点代码,发现当前页面ReactContext内的mCurrentActivity为空,取不到Activity。RN里大量内部桥/事件调用与第三方实现均依赖从ReactContext里拿Activity,拿不到当然就炸了啊。ReactContext的问题关注ReactContext中的mCurrentActivity设置与空置逻辑。a. 当hostActivity生命周期onResume的时候(还有onNewIntent,本次讨论不涉及),会设置mCurrentActivity。
//ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java
  public void onHostResume(@Nullable Activity activity) {
    mLifecycleState = LifecycleState.RESUMED;
    mCurrentActivity = new WeakReference(activity); // <---------- this 
    ReactMarker.logMarker(ReactMarkerConstants.ON_HOST_RESUME_START);
    for (LifecycleEventListener listener : mLifecycleEventListeners) {
      try {
        listener.onHostResume();
      } catch (RuntimeException e) {
        handleException(e);
      }
    }
    ReactMarker.logMarker(ReactMarkerConstants.ON_HOST_RESUME_END);
  }
b. 当hostActivity生命周期onDestroy的时候,会将当前ReactContext置为null。
//ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java
  public void onHostDestroy() {
    UiThreadUtil.assertOnUiThread();
    mLifecycleState = LifecycleState.BEFORE_CREATE;
    for (LifecycleEventListener listener : mLifecycleEventListeners) {
      try {
        listener.onHostDestroy();
      } catch (RuntimeException e) {
        handleException(e);
      }
    }
    mCurrentActivity = null; // <---------- this 
  }
这里注意到ReactNative Android特意设计了hostActivity与ReactContext分离的设计,一个ReactContext运行中对应的Activity可以不断发生改变。类似于支持多Activity共用同一个Context的即现代RN框架常见的引擎缓存复用模式,同时mCurrentActivity预期储存的是当前最上展示的Activity。因此发生异常的条件一定是,RN页面的最后一次生命周期调用是onDestroy。因此开始断点生命周期:- 第一次进入 RN-A onCreate -> onResume- 绑定动作 thisReactContext.mCurrentActivity => RN-A- XYZ结束操作 RN-B onCreate -> onResume- 绑定动作 thisReactContext.mCurrentActivity => RN-B- RN-A 销毁 -> onDestroy- 解绑动作  thisReactContext.mCurrentActivity => null明显出现预期之外的事件,塑料管材生产线即RN-B创建早于RN-A销毁。不过想想也很自然,Android端在同时发生多个页面关闭/打开,即页面替换时,页面生命周期并不是连续的,实际上onDestroy可能会稍晚于预期,容易发生异步生命周期问题,老问题了。因此根据记录的生命周期,实际上A的销毁晚于B的创建,因此最后一次生命周期调用为onDestroy,将复用的ReactContext持有Activity置为空。同理可以解释当前后台切换时,onResume会恢复设置Activity,页面功能恢复。用图描述ReactContext中持有的Activity状态如下:680) {this.resized=true; this.width=680;}">咋修短期方案1. 避免引擎复用的RNActivity连续关闭打开。具体操作方式为,XYZ流程结束后直接其上打开RN-B,RN-B关闭时再执行清栈并回退到根页面。(实际采用了此方案)2. 关闭引擎复用。(对性能影响较大,未使用)长期方案A销毁的时候将mCurrentActivity置为空,需判断mCurrentActivity中是否持有的自己,否则不应该置为空。
//ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java
  public void onHostDestroy() {
    //code before
    mCurrentActivity = null;
  }

/******* 改为 ********/

  public void onHostDestroy(Nullable Activity activity) {
    //code before
    if (mCurrentActivity.get() == activity) {
      mCurrentActivity = null; 
    }
  }
onHostDestroy对应方法调用方也需要修改,主要在Activity里,看起来影响面比较大,不过确实是最合理的改法了。另外对于FB的RN仓库来说,这个改动对于标准RN使用者有严重的break级变更,估计短期内只能在自己fork的版本上修复了。

陕西塑料挤出机设备

文安县建仓机械厂

数字足迹,通常指个人在使用数字设备或互联网后,保存在服务器端的相关数据,可分为被动型数字足迹,例如手机App静默收集位置、网站Cookie收集偏好等被动留痕信息;以及主动型数字足迹,例如社交媒体动态、网购记录等因个人主动行为产生的信息。它们在构成个人身份标识的同时,也因大数据技术而聚沙成塔,绘制出超出想象的宏观图景。

陕西塑料挤出机设备

视频显示,宇树科技G1人形机器人与王力宏共同演绎《火力全开》,实现了全球首个演唱会机器人舞台。

据某最新上线的机器人租赁平台介绍,该公司提供基础版、舞蹈版机器人及机器狗租赁,日租金从200元起,提供年会表演等场景服务,还计划引入机器人操作员培训和保险服务。

陕西塑料挤出机设备