<xmp id="63nn9"><video id="63nn9"></video></xmp>

<xmp id="63nn9"></xmp>

<wbr id="63nn9"><ins id="63nn9"></ins></wbr>

<wbr id="63nn9"></wbr><video id="63nn9"><ins id="63nn9"><table id="63nn9"></table></ins></video>

APP中RN頁面渲染流程-ReactNative源碼分析

在APP啟動后,RN框架開始啟動。等RN框架啟動后,就開始進行RN頁面渲染了。
RN頁面原生側頁面渲染的主要邏輯實現是在RCTUIManager和RCTShadowView完成的。
通過看UIMananger的源碼可以看到,UIMananger導出給JS端的API接口在對UI的操作上,基本都會同時對 View 和 ShadowView 進行操作。
以更新視圖為例:


RCTUIManager的作用
RCTUIManager的主要作用是負責管理React Native應用程序的視圖的創建、更新和銷毀。
具體為RCTUIManager負責創建并管理應用程序中的所有視圖,包括文本、圖像、按鈕等。當需要更新或銷毀視圖時,RCTUIManager會負責處理相應的操作。
 
 
RCTShadowView的作用 
RCTShadowView的主要作用是在APP中創建一棵YaGoNode節點樹,用于記錄視圖的樣式、布局、事件響應等信息,用于描述真實視圖的屬性和布局,從而提高渲染性能和效率。,它和UIView的關系類似于前端的虛擬DOM樹和DOM樹,兩者是一一對應的關系。js對View的操作會先更新虛擬DOM,然后ReactNative在合適的時機批量更新到真實的View上。

RN頁面的創建
在創建自定義RCTView供js使用時,一般在創建一個RCTView時,都要創建一個對應的RCTViewManager用于管理Native與js的通訊。
UIMananger的創建在RN框架啟動時,它在創建時會通過RCT_EXPORT_METHOD()宏將操作view的添加,修改,刪除,調整層級等方法注入給js,供js操作原生view
RN框架啟動完成后則會進行RN頁面渲染。
 
首先,js引擎執行rn代碼,將rn中的組件轉換成原生view展示到頁面上。
js引擎執行js代碼, 它會根據RN頁面中的標簽類型轉換成一棵虛擬DOM樹,它們有原子組件,文本組件,組合組件組成。在這些組件的內部記錄著create視圖需要的參數。等要生成真實的視圖時,就會調用指令生成對應的視圖。

原生側createView方法的主要執行步驟為:

RCT_EXPORT_METHOD(createView
: (nonnull NSNumber *)reactTag viewName
: (NSString *)viewName rootTag
: (nonnull NSNumber *)rootTag props
: (NSDictionary *)props)
1.根據模塊名viewName從RCTBridge保存的全局變量中找到對應的模塊信息
2.根據模塊信息創建shadowview虛擬dom,保存到shadowView全局容器中
3.根據模塊信息在主線程創建原生view,保存到view全局容器中
 
然后,執行setChildren:設置子視圖
執行setChildren:設置子視圖, 會將view添加到容器view的reactSubviews中(shadowView和UIView都是放到對應容器的reactSubviews屬性中)[container insertReactSubview:view atIndex:index++];

原生側setChildren方法的主要執行步驟為:

RCT_EXPORT_METHOD(setChildren : (nonnull NSNumber *)containerTag reactTags : (NSArray<NSNumber *> *)reactTags)
1.設置shadowView子視圖,shadowView是設置到yoga樹的葉子節點中:YGNodeInsertChild(_yogaNode, subview.yogaNode, (uint32_t)atIndex);
2.把設置view子視圖任務添加到任務隊列,[_pendingUIBlocks addObject:block];隊列中的任務并不會立刻執行,而是等到合適的時機再執行。而當這個任務執行后,子View也并沒有到真實的subviews中,而是放置到了reactSubviews關聯屬性中 objc_setAssociatedObject(self, @selector(reactSubviews), subviews, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
 
_pendingUIBlocks隊列執行時機
_pendingUIBlocks隊列的刷新時機主要有2種,一種是在JS代碼執行完成,JS通過RCTCxxBridge調用batchDidComplete觸發刷新。另一種在原生APP中根據RN頁面的布局手動調用setNeedsLayout進行觸發。
JS通過RCTCxxBridge調用
在js執行期間,js引擎通過Bridge橋接,把涉及到UI操作的事件按順序封裝成UIBlock放到Native原生側的_pendingUIBlocks中,在等js代碼執行完成后,原生模塊會觸發一個UIManager.batchDidComplete事件,表示js批量任務執行完成,開始刷新_pendingUIBlocks隊列中的UI任務了。因此,在 JavaScript 執行完成前,RN 頁面的 UI 并不會立即刷新。
方法調用順序:batchDidComplete -> _layoutAndMount -> flushUIBlocksWithCompletion。
_pendingUIBlocks中的UIBlock執行后,最終會生成真實的原生view
struct RCTInstanceCallback : public InstanceCallback {
  __weak RCTCxxBridge *bridge_;
  RCTInstanceCallback(RCTCxxBridge *bridge) : bridge_(bridge){};
  void onBatchComplete() override
  {
    // There's no interface to call this per partial batch
    [bridge_ partialBatchDidFlush];
    [bridge_ batchDidComplete];
  }
};
RN頁面根據頁面布局手動調用
- (void)setSize:(CGSize)size forView:(UIView *)view
{
  RCTAssertMainQueue();
  [self
      _executeBlockWithShadowView:^(RCTShadowView *shadowView) {
        if (CGSizeEqualToSize(size, shadowView.size)) {
          return;
        }

        shadowView.size = size;
        [self setNeedsLayout];
      }
                           forTag:view.reactTag];
}
- (void)setNeedsLayout
{
  // If there is an active batch layout will happen when batch finished, so we will wait for that.
  // Otherwise we immediately trigger layout.
  if (![_bridge isBatchActive] && ![_bridge isLoading]) {
    [self _layoutAndMount];
  }
}
RN頁面更新
當組件調用了setState屬性更新時,通過updateView:刷新視圖。
當出現插入、刪除、排序組件時,通過manageChildren:更新視圖。
updateView:刷新視圖
當在RN中通過setState更改屬性,js會對應生成一個新的虛擬DOM,通過diff算法,對應新舊DOM樹生成修改點,然后通過updateView事件,將屬性更新更新到原生側的shadowView和View的_UIPendingQueue中。
 
當出現插入、刪除、排序組件時,通過manageChildren:更新視圖
containerTag:表示容器組件的標識符,即將在其中管理子組件。
moveFromIndices和moveToIndices:表示要移動的子組件的原始位置和目標位置的索引。
addChildReactTags和addAtIndices:表示要添加的子組件的標識符和它們在父容器中的位置索引。
removeAtIndices:表示要從父容器中刪除的子組件的位置索引。
registry:表示React組件的注冊表,其中包含所有已注冊的組件及其實例。

 

 
 
 
 
posted @ 2023-05-24 23:09  滴水微瀾  閱讀(160)  評論(0編輯  收藏  舉報
人碰人摸人爱免费视频播放

<xmp id="63nn9"><video id="63nn9"></video></xmp>

<xmp id="63nn9"></xmp>

<wbr id="63nn9"><ins id="63nn9"></ins></wbr>

<wbr id="63nn9"></wbr><video id="63nn9"><ins id="63nn9"><table id="63nn9"></table></ins></video>