將React Native集成到現有的android項目中

React Native很強大,但對於初學者來說,直接將現有的項目轉成React Native顯然是不現實的,畢竟其中需要考慮的問題也比較多,功能點的實現是最基礎的,如何進行適配,性能問題界面會不會非常卡等等,這些都是很容易遇到的。那這裏最好的方法就是逐步的去學習React Native,將新的需求試着用React Native去實現,再解決了一個個坑後,熟悉了整個開發過程,這樣風險就能控制在最低。這裏React Native也提供了接入原生項目的方法,可以參考中文官網,下面會給出具體步驟以及我在整個過程中遇到的一些問題。

一、生成Android項目

使用Android Studio直接新建一個項目,這裏有兩點需要強調的是:

(1)minSdkVersion要高於15
(2)com.android.support:appcompat-v7 的版本不能是26,否則會報衝突異常。

二、生成package.json文件和node_modules(一些依賴庫)

在根目錄輸入npm init 生成package.json,填入一些基本信息,name最好是小寫。

輸入npm install --save react react-native
如果需要手動設置react版本可以輸入:npm install --save [email protected]
將對應版本號進行替換即可,這裏推薦第一種方法,指定版本的用法好像會導致一些文件缺失,最後在生成assets文件時會報錯
生成後的package.json中加入下面一句話:
"start": "node node_modules/react-native/local-cli/cli.js start"
最終package.json展示如下:

三、新建index.android.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('react-example', () => HelloWorld);
這裏registerComponent方法的第一個參數要記住,之後Android代碼調用的時候會用到

四、配置基本環境

Android添加React依賴:
在App 的 build.gradle中加入
compile "com.facebook.react:react-native:+" // From node_modules.
這裏的加號可以替換成具體的版本號
要加上下面這句話,否則同步時會報錯
configurations.all{
    resolutionStrategy.force 'com.google.code.findbugs:jsr305:1.3.9'
}

在項目的build.gradle中加入
maven {
    url "$rootDir/node_modules/react-native/android"
}

成功後會在External Libraries中顯示出來,如下:


這裏的加號可以替換成具體的版本號
要加上下面這句話,否則同步時會報錯

在AndroidManifest.xml中聲明網絡權限
<uses-permission android:name="android.permission.INTERNET" />
在AndroidManifest.xml中聲明配置的Activity
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />

這個配置的Activity還是十分好用的,可以設置一系列調試方法

public class MyReactActivity extends AppCompatActivity 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();
 
    // 注意這裏的react-example必須對應“index.android.js”中的
    // “AppRegistry.registerComponent()”的第一個參數
    mReactRootView.startReactApplication(mReactInstanceManager, "react-example", null);
 
    setContentView(mReactRootView);
  }
 
  @Override
  public void invokeDefaultOnBackPressed() {
    super.onBackPressed();
  }
 
  @Override
  protected void onPause() {
    super.onPause();
 
    if (mReactInstanceManager != null) {
      mReactInstanceManager.onHostPause(this);
    }
  }
 
  @Override
  protected void onResume() {
    super.onResume();
 
    if (mReactInstanceManager != null) {
      mReactInstanceManager.onHostResume(this, this);
    }
  }
 
  @Override
  protected void onDestroy() {
    super.onDestroy();
 
    if (mReactInstanceManager != null) {
      mReactInstanceManager.onHostDestroy();
    }
  }
 
  @Override
  public void onBackPressed() {
    if (mReactInstanceManager != null) {
      mReactInstanceManager.onBackPressed();
    } else {
      super.onBackPressed();
    }
  }
 
  @Override
  public boolean onKeyUp(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
      mReactInstanceManager.showDevOptionsDialog();
      return true;
    }
    return super.onKeyUp(keyCode, event);
  }
}
ReactRootView 是關鍵,也可以在佈局文件中加上這個控件,這裏ReactInstanceManager的一些方法在React 0.20.X版本和它之上的版本有很大的區別,這裏最好使用較新的版本

五、運行項目

直接運行Android項目,發現會報錯因爲沒有生成對應的bundle文件也沒有啓動遠程服務進行調試,


(1)生成對應的bundle文件

需要新建assets文件夾,運行下面命令:
react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output app/src/main/assets/index.android.bundle --sourcemap-output app/src/main/assets/index.android.map --assets-dest app/src/main/res/

在assets目錄下會生成對應幾個文件


再運行會發現沒有報錯了,但是如果你隨便修改一個東西想要立刻看到效果可以使用第二種方法,這個方法多使用在最終打包的時候。

(2)npm start 運行服務

除了啓動服務之外你還需要打開設置界面,在設置界面中修改ip地址,這裏根據官網的方法搖一搖手機發現並沒有出現菜單界面,代碼中還需要修改:

mReactRootView = new ReactRootView(this);
mReactInstanceManager = ReactInstanceManager.builder()
    .setApplication(getApplication())
    .setBundleAssetName("index.android.bundle")
    .setJSMainModuleName("index.android")
    .addPackage(new MainReactPackage())
//        .setUseDeveloperSupport(BuildConfig.DEBUG) //開發者支持,BuildConfig.DEBUG的值默認是false,無法使用開發者菜單
    .setUseDeveloperSupport(true)        //開發者支持,開發的時候要設置爲true,不然無法使用開發者菜單
    .setInitialLifecycleState(LifecycleState.RESUMED)
    .build();
 
// 注意這裏的react-example必須對應“index.android.js”中的
// “AppRegistry.registerComponent()”的第一個參數
mReactRootView.startReactApplication(mReactInstanceManager, "peoplus", null);

這裏新版本中setJSMainModuleName方法無法使用,用setJSMainModulePath方法代替,之後搖一搖手機或者輸入命令adb shell input keyevent 82就可以打開設置界面


這裏點擊Dev Settings打開設置界面


設置成功後重新點擊Reload就可以調試了,之後只要代碼做了修改,直接Reload就可以看到修改效果,非常方便。

這裏之後也會專門說下如何調試React Native項目,也是有很多方法的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章