当拿到一个项目的时候,我们要知道项目是如何运行起来的,这样方便我们更能理解项目的原理,也能帮助我们以后排错和优化。
本文的大致思路可以分为三步:
- 找到整个应用的入口文件
- 找到 native 端和 React Native 相连接的方法
- 找到 React Native 的入口文件
根据以上三步,就可以知道整个项目是如何运行的了。下面我们一起来寻找吧~
用 Android Stutio 打开项目根目录下的 Android 文件夹,我们能看到下面的文件分布:
- app 文件夹里面是 Android 的配置文件
- app 文件下面的文件都是我们需要的原生组件
整个应用的入口文件
打开 app - manifest,我们看到里面有一个AndroidManifest.xml
文件。此文件是整个应用的入口,配置了程序运行所必须的组件、启动位置以及一些其他的信息。
打开 AndroidManifest.xml
文件我们能看到下面的内容:
我们看到在这个文件中主要有以下节点:
- manifest
- uses-permission
- uses-sdk
- application
- activity
下面就各个节点来做一个介绍:
AndroidManifest.xml
文件里主要是一个 manifest
节点,然后包裹其他的节点,通过配置不同的属性来得到我们想要的效果。
manifest
xmlns:android
它是用来定义 android 的命名空间的,一般为http://schemas.android.com/apk/res/android
。有了它之后,就能够使用 Android 中各种的标准属性了。package
是本项目内 java 主程序包的包名,也是一个应用进程的默认名称。android:versionCode
interger 值。设备程序通过它来识别版本信息,代表 app 更新过多少次,1 代表 1 次,再更新的话就设置为 2,以此类推等等。android:versionName
这个值是给用户看的,设备可以是 1.0 版本,后续更新的话可以设置为 1.1、1.2 等等。
uses-permission
通过字面意思我们可以大致的认为它是需要和用户进行操作的。其实就是,app 安装的时候需要向用户索要的一些权限,用户可以同意也可以拒绝。
android:name
即需要使用的权限的名字,可以是系统自带的权限,也可以是自定义的权限。
uses-sdk
uses-sdk
是用来设置 app
对 android
系统的兼容性的。我们用了以下两个配置项,配置项的值是一个代表 Android API Level
参数的整数。每个 API Level
对应着一个 Android 系统的版本。下图为官方给出的 API Level
和 Android 系统版本的对照表。
android:minSdkVersion
一个用于指定应用运行所需最低 API 级别的整数。 如果系统的 API 级别低于该属性中指定的值,Android 系统将阻止用户安装应用。android:targetSdkVersion
一个用于指定应用的目标API
级别的整数。如果未设置,其默认值与为minSdkVersion
指定的值相等。一般情况下应该将这个属性的值设置为最新的API level
值,这样我们才可以利用新版本系统上的新特性。
Application
每个 Android 应用程序启动的时候都会初始化一个 Application 类。我们可以通过它来定义一些全局的和一些上下文都要用到的变量和方法。
Application 的生命周期是整个应用中最长的,可以说它的生命周期就是整个应用的生命周期。
android:name
一般情况下系统会自动创建一个 Application 类。如果我们需要自定义一个 Application 类的话,需要创建一个类并且继承 Application。然后在 name 属性中写上自定义的 Application 类名即可。android:allowBackup
Android API Level 8
及其以上 Android 系统提供了为应用程序数据的备份和恢复功能。此属性就是控制该功能的开关。系统默认为 true。当allowBackup
标志为true
时,用户可通过adb backup
和adb restore
来进行对应用数据的备份和恢复。android:label
显示给用户的 APP 的名称android:icon
APP 的图标所在的路径。android:theme
它给所有的 Activity 定义了一个默认的主题风格,也可以在自己的 theme 里设置。
Activity
每个 Activity 都会获得一个用于绘制其用户界面的窗口。窗口通常会充满屏幕,但也可小于屏幕并浮动在其他窗口之上。
android:name
如果第一个字节是小数点,那么会自动的在类别名称前加上这个项目的package
名称。看到上面的例子中,咱们把android:name
设为了.MainActivity
,所以项目读取的时候应该为com.myapp.MainActivity
。android:label
Activity 的标题,可以覆盖 Application 的 label。android:configChanges
当手机进行横屏和竖屏的切换时,是否调用onConfigurationChanged()
方法。
如果不设置此属性,当 Android 手机旋转后,会把当前 Activity 杀掉,然后根据方向重新加载这个Activity,就会从 onCreate 开始重新加载。
如果设置了此属性,当手机旋转后,当前 Activity 就会调用onConfigurationChanged()
方法,而不是调用 onCreate 方法。android:screenOrientation
activity
显示的模式。
默认为unspecified
:由系统自动判断显示方向landscape
横屏模式,宽度比高度大portrait
竖屏模式, 高度比宽度大user
模式,用户当前首选的方向behind
模式:和该Activity下面的那个Activity的方向一致(在Activity堆栈中的)sensor
模式:有物理的感应器来决定。如果用户旋转设备这屏幕会横竖屏切换nosensor
模式:忽略物理感应器,这样就不会随着用户旋转设备而更改了android:windowSoftInputMode
activity
主窗口与软键盘的交互模式,可以用来避免输入法面板遮挡问题,Android1.5
后的一个新特性。adjustResize
:该Activity
总是调整屏幕的大小以便留出软键盘的空间
注意: 看到上面的代码里 activity
内还有 intent-filter
元素,说明这个 activity
会在应用启动的时候第一个被执行。
intent-filter
action
android:name
值为android.intent.action.MAIN
,表明此 Activity 是作为应用程序的入口。category
android:name
值为android.intent.category.LAUNCHER
,表明应用程序是否显示在程序列表里。
native 端和 React Native 相连接的方法
MainActivity
通过上面的一些介绍,我们可以知道,有 intent-filter
节点,并且它的 action
的 android:name
为 android.intent.action.MAIN
的 Activity 为本项目的入口。那我们就可以顺藤摸瓜,一步一步的往下走。
打开 com.myapp
下的 MainActivity
文件,找到 onCreate
方法。这个方法主要是显示悬浮窗,并且加载 App。如果无权使用悬浮窗,则会提醒用户授权。
加载 app 的方法是 loadapp()
方法:
|
|
- 第一步
mReactRootView = new ReactRootView(this)
的意思是实例化ReactRootView
,并将它作为Activity
的根view
。 setApplication
的意思是把 native 端的Application
对象赋给 React Native。setJSMainModuleName
的参数是 js 的入口文件 ——index.android.js
,index.android.js
文件的路径是相对于package.json
的路径。addPackage
是自定义 React Native 的 Android 组件。setUseDeveloperSupport
表示是否启用开发者模式。这里写BuildConfig.DEBUG
就可以自动根据 gradle 构建的类型(debug或release)来决定。mReactRootView.startReactApplication
方法是启动整个 React Native 程序。setContentView
方法是将mReactRootView
作为子布局加载到 Activity 中。
React Native 的入口文件
AppRegistry
是JS运行所有React Native应用的入口。通过 AppRegistry.registerComponent
来注册项目的根组件,然后原生系统才可以加载应用的代码包并且在启动完成之后通过调用 AppRegistry.runApplication
来真正运行应用。