React-Native android源代碼分析-視圖創(chuàng)建

記錄自己分析RN的過程。
先看入口的MainActivity,它是繼承自ReactActivity 的刊头。
ReactActivity的內(nèi)容

/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

package com.facebook.react;

import javax.annotation.Nullable;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.KeyEvent;

import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
import com.facebook.react.modules.core.PermissionAwareActivity;
import com.facebook.react.modules.core.PermissionListener;

/**
 * Base Activity for React Native applications.
 */
public abstract class ReactActivity extends Activity
    implements DefaultHardwareBackBtnHandler, PermissionAwareActivity {

  private final ReactActivityDelegate mDelegate;

  protected ReactActivity() {
    mDelegate = createReactActivityDelegate();
  }

  /**
   * Returns the name of the main component registered from JavaScript.
   * This is used to schedule rendering of the component.
   * e.g. "MoviesApp"
   */
  protected @Nullable String getMainComponentName() {
    return null;
  }

  /**
   * Called at construction time, override if you have a custom delegate implementation.
   */
  protected ReactActivityDelegate createReactActivityDelegate() {
    return new ReactActivityDelegate(this, getMainComponentName());
  }

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mDelegate.onCreate(savedInstanceState);
  }

  @Override
  protected void onPause() {
    super.onPause();
    mDelegate.onPause();
  }

  @Override
  protected void onResume() {
    super.onResume();
    mDelegate.onResume();
  }

  @Override
  protected void onDestroy() {
    super.onDestroy();
    mDelegate.onDestroy();
  }

  @Override
  public void onActivityResult(int requestCode, int resultCode, Intent data) {
    mDelegate.onActivityResult(requestCode, resultCode, data);
  }

  @Override
  public boolean onKeyUp(int keyCode, KeyEvent event) {
    return mDelegate.onKeyUp(keyCode, event) || super.onKeyUp(keyCode, event);
  }

  @Override
  public void onBackPressed() {
    if (!mDelegate.onBackPressed()) {
      super.onBackPressed();
    }
  }

  @Override
  public void invokeDefaultOnBackPressed() {
    super.onBackPressed();
  }

  @Override
  public void onNewIntent(Intent intent) {
    if (!mDelegate.onNewIntent(intent)) {
      super.onNewIntent(intent);
    }
  }

  @Override
  public void requestPermissions(
    String[] permissions,
    int requestCode,
    PermissionListener listener) {
    mDelegate.requestPermissions(permissions, requestCode, listener);
  }

  @Override
  public void onRequestPermissionsResult(
    int requestCode,
    String[] permissions,
    int[] grantResults) {
    mDelegate.onRequestPermissionsResult(requestCode, permissions, grantResults);
  }

  protected final ReactNativeHost getReactNativeHost() {
    return mDelegate.getReactNativeHost();
  }

  protected final ReactInstanceManager getReactInstanceManager() {
    return mDelegate.getReactInstanceManager();
  }

  protected final void loadApp(String appKey) {
    mDelegate.loadApp(appKey);
  }
}

其中仗颈,這個類吧所有的操作都交給一個ReactActivityDelegate對象來執(zhí)行佛舱。
我想主要原因是,這個類需要經(jīng)常被繼承挨决,如果直接在這個類實現(xiàn)方法请祖,不免會讓其子類變得臃腫。使用代理的方法就避免了這個問題脖祈。

先看其最核心的入口肆捕,onCreate .這個類來創(chuàng)建視圖等。
我們在做安卓開發(fā)時一般在這類初始化視圖盖高。
使用setContentView傳入一個layout的id慎陵,或者一個view對象。

我們跟進Delegate中或舞,看到

  protected void onCreate(Bundle savedInstanceState) {
    boolean needsOverlayPermission = false;
    if (getReactNativeHost().getUseDeveloperSupport() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
      // Get permission to show redbox in dev builds.
      if (!Settings.canDrawOverlays(getContext())) {
        needsOverlayPermission = true;
        Intent serviceIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getContext().getPackageName()));
        FLog.w(ReactConstants.TAG, REDBOX_PERMISSION_MESSAGE);
        Toast.makeText(getContext(), REDBOX_PERMISSION_MESSAGE, Toast.LENGTH_LONG).show();
        ((Activity) getContext()).startActivityForResult(serviceIntent, REQUEST_OVERLAY_PERMISSION_CODE);
      }
    }

    if (mMainComponentName != null && !needsOverlayPermission) {
      loadApp(mMainComponentName);
    }
    mDoubleTapReloadRecognizer = new DoubleTapReloadRecognizer();
  }

對于androidM荆姆,請求了android.settings.action.MANAGE_OVERLAY_PERMISSION權(quán)限。

隨后判斷mMainComponentName 是否為空映凳。這個變量的初始化是在其構(gòu)造函數(shù)中

  public ReactActivityDelegate(Activity activity, @Nullable String mainComponentName) {
    mActivity = activity;
    mMainComponentName = mainComponentName;
    mFragmentActivity = null;
  }

這個構(gòu)造函數(shù)的調(diào)用者是ReactActivity的create..方法

  protected ReactActivityDelegate createReactActivityDelegate() {
    return new ReactActivityDelegate(this, getMainComponentName());
  }

是通過getMainComponentName獲取的胆筒。而這個方法子類可以繼承和修改。

我們回到onCreate中诈豌。
調(diào)用 loadApp(mMainComponentName); 接著調(diào)用
DoubleTapReloadRecognizer (這個應該是雙擊R重新加載)

loadApp代碼

  protected void loadApp(String appKey) {
    if (mReactRootView != null) {
      throw new IllegalStateException("Cannot loadApp while app is already running.");
    }
    mReactRootView = createRootView();
    mReactRootView.startReactApplication(
      getReactNativeHost().getReactInstanceManager(),
      appKey,
      getLaunchOptions());
    getPlainActivity().setContentView(mReactRootView);
  }

如果mReactRootView已經(jīng)有了仆救,就不需要load了。

調(diào)用createRootView創(chuàng)建矫渔。

  protected ReactRootView createRootView() {
    return new ReactRootView(getContext());
  }

其實是調(diào)用了構(gòu)造函數(shù)彤蔽。轉(zhuǎn)到ReactRootView看一下。

public class ReactRootView extends SizeMonitoringFrameLayout implements RootView {
...
}

這是一個SizeMonitoringFrameLayout 庙洼,它又是一個FrameLayout顿痪。

好了∮凸唬總結(jié)來說蚁袭,在ReactActivity創(chuàng)建的時候使用了一個ReactRootView作為其跟視圖。

未完待續(xù)石咬。揩悄。。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鬼悠,一起剝皮案震驚了整個濱河市删性,隨后出現(xiàn)的幾起案子亏娜,更是在濱河造成了極大的恐慌,老刑警劉巖蹬挺,帶你破解...
    沈念sama閱讀 222,946評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件维贺,死亡現(xiàn)場離奇詭異,居然都是意外死亡巴帮,警方通過查閱死者的電腦和手機幸缕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,336評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來晰韵,“玉大人发乔,你說我怎么就攤上這事⊙┲恚” “怎么了栏尚?”我有些...
    開封第一講書人閱讀 169,716評論 0 364
  • 文/不壞的土叔 我叫張陵,是天一觀的道長只恨。 經(jīng)常有香客問我译仗,道長,這世上最難降的妖魔是什么官觅? 我笑而不...
    開封第一講書人閱讀 60,222評論 1 300
  • 正文 為了忘掉前任纵菌,我火速辦了婚禮,結(jié)果婚禮上休涤,老公的妹妹穿的比我還像新娘咱圆。我一直安慰自己,他們只是感情好功氨,可當我...
    茶點故事閱讀 69,223評論 6 398
  • 文/花漫 我一把揭開白布序苏。 她就那樣靜靜地躺著,像睡著了一般捷凄。 火紅的嫁衣襯著肌膚如雪忱详。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,807評論 1 314
  • 那天跺涤,我揣著相機與錄音匈睁,去河邊找鬼。 笑死桶错,一個胖子當著我的面吹牛航唆,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播牛曹,決...
    沈念sama閱讀 41,235評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼佛点,長吁一口氣:“原來是場噩夢啊……” “哼醇滥!你這毒婦竟也來了黎比?” 一聲冷哼從身側(cè)響起超营,我...
    開封第一講書人閱讀 40,189評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎阅虫,沒想到半個月后演闭,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,712評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡颓帝,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,775評論 3 343
  • 正文 我和宋清朗相戀三年米碰,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片购城。...
    茶點故事閱讀 40,926評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡吕座,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出瘪板,到底是詐尸還是另有隱情吴趴,我是刑警寧澤,帶...
    沈念sama閱讀 36,580評論 5 351
  • 正文 年R本政府宣布侮攀,位于F島的核電站锣枝,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏兰英。R本人自食惡果不足惜撇叁,卻給世界環(huán)境...
    茶點故事閱讀 42,259評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望畦贸。 院中可真熱鬧陨闹,春花似錦、人聲如沸薄坏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,750評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽颤殴。三九已至觅廓,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間涵但,已是汗流浹背杈绸。 一陣腳步聲響...
    開封第一講書人閱讀 33,867評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留矮瘟,地道東北人瞳脓。 一個月前我還...
    沈念sama閱讀 49,368評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像澈侠,于是被迫代替她去往敵國和親劫侧。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,930評論 2 361

推薦閱讀更多精彩內(nèi)容