已有 Android 项目集成 react-native

一:前言

为了配合运营和市场伙伴的工作,app中一些模块或界面需要频繁变动。于Android,可以使用webview, 热更新和rn等方法。其中webview 较为常规, 但加载速度慢,热更新还没接触(部分大厂在用),rn的话看起来很美(facebook出品,github star多),所以我选择rn进行尝试,此文是我集成rn的一个总结。

二: Android 项目配置

预设读者已经成功配置rn,as,并熟悉as工程下文件目录,遇到问题可以google。

  • 新建文件夹,命名为androidwithreact
  • 进入androidwithreact文件夹,新建android文件夹
  • 将原有的android项目复制到android文件夹下
  • 修改android/build.gradle文件,配置rn版本
    <pre><code>allprojects {
    repositories {
    jcenter()    
    mavenLocal()
    maven {
        url &quot;$rootDir/../node_modules/react-native/android&quot;
        }
    }
    
    }
  • 修改app(module)下build.gradle 在dependencies中添加
    compile 'com.facebook.react:react-native:+'
  • 在manifest文件中添加一下代码方便进入开发者模式
    <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
  • 新建activity作为rn呈现的载体

    
    public class ReactActivity extends AppCompatActivity implements     
    DefaultHardwareBackBtnHandler {        
    
      private ReactRootView mReactRootView;
      private ReactInstanceManager mReactInstanceManager;
    
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
    
          //创建一个ReactRootView,把它设置成Activity的主视图
              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();
              mReactRootView.startReactApplication(mReactInstanceManager, "androidwithreact", null);
              setContentView(mReactRootView);
          }
    
          @Override
          public void invokeDefaultOnBackPressed() {
              super.onBackPressed();
          }
    
          //传递一些Activity的生命周期事件到ReactInstanceManager,这是的JavaScript代码可以控制当前用户按下返回按钮的时候作何处理(譬如控制导航切换等等)。如果JavaScript端不处理相应的事件,你的invokeDefaultOnBackPressed方法会被调用。默认情况,这会直接结束你的Activity。
          @Override
          protected void onPause() {
              super.onPause();
    
              if (mReactInstanceManager != null) {
                  mReactInstanceManager.onHostPause();
              }
          }
    
          @Override
          protected void onResume() {
              super.onResume();
    
              if (mReactInstanceManager != null) {
                  mReactInstanceManager.onHostResume(this,this);
              }
          }
    
          @Override
          public void onBackPressed() {
              //mReactInstanceManager.showDevOptionsDialog();
              Toast.makeText(this, "dianjialefanhuijian", Toast.LENGTH_SHORT).show();
              if (mReactInstanceManager != null) {
                  mReactInstanceManager.onBackPressed();
              } else {
                  super.onBackPressed();
              }
          }
    
          //我们需要改动一下开发者菜单。默认情况下,任何开发者菜单都可以通过摇晃或者设备类触发,不过这对模拟器不是很有用。所以我们让它在按下Menu键的时候可以显示
          @Override
          public boolean onKeyUp(int keyCode, KeyEvent event) {
              if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
    
                  mReactInstanceManager.showDevOptionsDialog();
                  return true;
                  }
              return super.onKeyUp(keyCode, event);
              }
          }

三: rn配置

  • npm init 新建一个rn项目 里面有package.json和node_modules文件夹
  • 让我们回到androidwithreact文件夹下 将上述两个文件复制进来
  • 复制一个index.android.js 文件进来最后一行修改,第一个参数要修改

    AppRegistry.registerComponent('androidwithreact', () => xxx);

    四: 报错问题

  • module 0 …… stackoverflow上的解决方法是package.json中的rn版本与as中配置的版本不匹配,建议换成最新的。

  • v4包冲突 在android目录下的build.gradle中添加
    android {
      dexOptions {
          preDexLibraries = false
              }
          }
    
  • bundle not packaged correctly切换到androidwithreact目录下,执行npm start开启服务