React Native在Android當中實踐(一)——背景介紹
React Native在Android當中實踐(二)——搭建開發環境
React Native在Android當中實踐(三)——整合到Android專案當中
React Native在Android當中實踐(四)——程式碼整合
React Native在Android當中實踐(五)——常見問題
程式碼整合
Android Studio的環境配置完成之後 接下來我們開始對程式碼進行整合
index.js檔案
首先在專案根目錄中建立一個空的index.js檔案。(注意在0.49版本之前是index.android.js檔案) index.js是React Native應用在Android上的入口檔案。而且它是不可或缺的!
新增你自己的React Native程式碼
在這裡方便測試 我們只是簡簡單單寫一個js檔案進行測試
import React from 'react';import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';
class HelloWorld extends React.Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.hello}>Hello, World</Text>
</View>
)
}
}var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
},
hello: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
});
AppRegistry.registerComponent('MyReactNativeApp', () => HelloWorld);
複製程式碼
在這裡特別要注意的是:
這個名稱要和package.json當中的 保持一致,否則會出現異常。配置許可權以便開發當中的紅屏錯誤能夠正確的顯示。
如果你的應用會執行在Android 6.0(API level 23)或更高版本,請確保你在開發版本中有開啟懸浮窗(overlay)許可權。你可以在程式碼中使用Settings.canDrawOverlays(this);來檢查。之所以需要這一許可權,是因為我們會把開發中的報錯顯示在懸浮窗中(僅在開發階段需要)。在Android 6.0(API level 23)中使用者需要手動同意授權。具體請求授權的做法是在onCreate()中新增如下程式碼。其中OVERLAY_PERMISSION_REQ_CODE是用於回傳授權結果的欄位。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!Settings.canDrawOverlays(this)) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, OVERLAY_PERMISSION_REQ_CODE);
}
}
Finally, the onActivityResult() method (as shown in the code below) has to be overridden to handle the permission Accepted or Denied cases for consistent UX.
@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == OVERLAY_PERMISSION_REQ_CODE) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!Settings.canDrawOverlays(this)) {
// SYSTEM_ALERT_WINDOW permission not granted...
}
}
}
}
複製程式碼
如果不需要開發者,則不需要以上相關配置。
執行React Native
首先需要在一個Activity中建立一個ReactRootView物件,然後在這個物件之中啟動React Native應用,並將它設為介面的主檢視。 如果你想在安卓5.0以下的系統上執行,請用 com.android.support:appcompat 包中的 AppCompatActivity 代替 Activity 。
public class MyReactActivity extends Activity implements DefaultHardwareBackBtnHandler {
private ReactRootView mReactRootView;
private ReactInstanceManager mReactInstanceManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mReactRootView = new ReactRootView(this);
mReactInstanceManager = ReactInstanceManager.builder()
.setApplication(getApplication())
.setBundleAssetName("index.android.bundle")
.setJSMainModuleName("index.android")
.addPackage(new MainReactPackage())
.setUseDeveloperSupport(BuildConfig.DEBUG)
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
// 注意這裡的MyReactNativeApp必須對應“index.android.js”中的
// “AppRegistry.registerComponent()”的第一個引數
mReactRootView.startReactApplication(mReactInstanceManager, "MyReactNativeApp", null);
setContentView(mReactRootView);
}
@Override
public void invokeDefaultOnBackPressed() {
super.onBackPressed();
}
}
複製程式碼
如果你使用的是 Android Studio , 可以使用Alt + Enter快捷鍵來自動為MyReactActivity類補上缺失的import語句。注意BuildConfig應該是在你自己的包中自動生成,無需額外引入。千萬不要從com.facebook...的包中引入! 我們需要把 MyReactActivity 的主題設定為 Theme.AppCompat.Light.NoActionBar ,因為裡面有許多元件都使用了這一主題。
<activity
android:name=".MyReactActivity"
android:label="@string/app_name"
android:theme="@style/Theme.AppCompat.Light.NoActionBar">
</activity>
複製程式碼
一個ReactInstanceManager可以在多個activities或fragments間共享。 You will want to make your own ReactFragment or ReactActivity and have a singleton holder that holds a ReactInstanceManager. When you need the ReactInstanceManager (e.g., to hook up the ReactInstanceManager to the lifecycle of those Activities or Fragments) use the one provided by the singleton. 下一步我們需要把一些activity的生命週期回撥傳遞給ReactInstanceManager:
@Overrideprotected void onPause() {
super.onPause();
if (mReactInstanceManager != null) {
mReactInstanceManager.onHostPause(this);
}
}
@Overrideprotected void onResume() {
super.onResume();
if (mReactInstanceManager != null) {
mReactInstanceManager.onHostResume(this, this);
}
}
@Overrideprotected void onDestroy() {
super.onDestroy();
if (mReactInstanceManager != null) {
mReactInstanceManager.onHostDestroy();
}
}
複製程式碼
我們還需要把後退按鈕事件傳遞給React Native:
@Override
public void onBackPressed() {
if (mReactInstanceManager != null) {
mReactInstanceManager.onBackPressed();
} else {
super.onBackPressed();
}
}
@Overridepublic boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
mReactInstanceManager.showDevOptionsDialog();
return true;
}
return super.onKeyUp(keyCode, event);
}
複製程式碼
現在activity已就緒,可以執行一些JavaScript程式碼了。 在新版本的React Native的整合不必這麼麻煩 只需要簡單的繼承 ReactActivity 然後實現以下幾個方法
@Override
protected String getMainComponentName() {
return null;
}
@Override
protected boolean getUseDeveloperSupport() {
return false;
}
@Override
protected List<ReactPackage> getPackages() {
return null;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
複製程式碼
其中
protected String getMainComponentName() {
return null;
}
複製程式碼
方法需要返回的名稱即為
注意這裡的MyReactNativeApp必須對應“index.android.js”中的
“AppRegistry.registerComponent()”的第一個引數
名稱。
如圖:
public class MyApplication extends Application implements ReactApplication {
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage()
);
}
};
}
複製程式碼
在AndroidManifest.xml當中增加
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
複製程式碼
這個是除錯的Activity,若需要我們要整合到我們專案中的。 到此為止,ReactNative 整合到已有專案中完成!!!迫不及待的執行試試吧!! 執行ReactNative 首先,在Terminal當中執行 npm start命令(若整合了yarn 則直接執行yarn start即可) 若出現
則表示成功。為了確認 我們可以在瀏覽器當中輸入如下地址 http://localhost:8081/index.android.js 瀏覽器顯示我們的js檔案,則表示我們已經整合成功,如下圖。 然後執行專案 之所以有這個許可權,是因為在React Native測試環境下會如果有異常會有彈層所以我們允許許可即可。然後React Native正式的情況則不會有這個許可權。設定地方在Application當中的 這個地方進行配置