RN入门---环境搭建和第一个RN项目

一、RN环境的搭建,参照RN中文网,有以下概念

Chocolatey:Chocolatey是一个Windows上的包管理器,用于安装windows程序
Python 2
NodeJS:NodeJS是基于javascript的服务端。将本地的js文件(RN里,将返回的js文件通过依赖React翻译成React格式,再通过依赖react-native,翻译为react-native格式)返回客户端(即android端)。
bundle文件:react-native格式的js文件(react-native格式的js代码可以说是一个转换器,在nodejs端可以依赖react-native插件对应js代码,在android可以依赖react-native插件对应java代码,react-native插件是翻译官)是放在bundle文件内的,android端是和它交互的。当android端和nodejs端离线时,放在assets目录下;服务端启动时,直接返回bundle文件。android端一个RN界面从bundle中拿取当前界面需要的内容(如下图),并依赖react-native插件将这些内容映射为原生视图和事件处理。
android端一个RN页面需要的内容如下,需要和NodeJS端的主js文件导出的组件名一致(可以理解为将此页面的所有内容打包到这个名字下了):
android:
这里写图片描述
Js:
这里写图片描述
react-native-cli:相当于node.js的一个插件,相当于nodejs的一个入口。两个作用:1.初始化出一个带有支持RN组件的android Demo工程,2.该插件的作用还有当node.js服务启动后,当native端的APP发起JS请求时,检查服务端的js信息是否有更新,并将它们转化为react-native格式传给native端。
npm:node packege manage,node包管理器,负责nodejs的模块安装。装nodejs时,npm就已经自动安装好了。


二、当直接initRN项目时

很简单,直接调用”react-native init”命令即可。会从相关的远程copy配置好的工程目录层次到本地。


三、当将原生集成RN时:

RN入门---环境搭建和第一个RN项目_第1张图片
NodeJS端环境
1、将原生工程放入android文件夹内
2、在根目录下新建packege.json文件,填入以下内容(也可通过“npm init”命令实现),类似gradle配置文件:
RN入门---环境搭建和第一个RN项目_第2张图片
version字段没有太大意义(除非你要把你的项目发布到npm仓库)。scripts中是用于启动packager服务的命令。dependencies中的react和react-native的版本取决于你的具体需求。一般来说我们推荐使用最新版本。你可以使用npm info react和npm info react-native来查看当前的最新版本。另外,react-native对react的版本有严格要求,高于或低于某个范围都不可以。
3、执行“npm install”命令安装后,就会生成”node_moudles”文件夹。

Android端环境
1、在你的app中 build.gradle 文件中添加 React Native 依赖:
这里写图片描述
2、为确保android端和nodejs端react-native版本一致,在项目的 build.gradle 文件中为 React Native 添加一个 maven 依赖的入口,必须写在 “allprojects” 代码块中:
RN入门---环境搭建和第一个RN项目_第3张图片
3、因为要和nodejs端交互,添加网络权限
这里写图片描述
4、如果需要访问 DevSettingsActivity 界面(即开发者菜单),则还需要在 AndroidManifest.xml 中声明,开发者菜单一般仅用于在开发时从Packager服务器刷新JavaScript代码,所以在正式发布时你可以去掉这一权限。
这里写图片描述

android端代码
一个rn界面:

//该Activity不用直接继承ReactActivity,但是实现DefaultHardwareBackBtnHandler接口,以处理相关的手机按键事件
public class RNSceActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler {

private static final int OVERLAY_PERMISSION_REQ_CODE = 102;
private static final String TAG = "---";
private ReactRootView mReactRootView;//JS对应的Native的根布局
private ReactInstanceManager mReactInstanceManager;//Instance 管理器

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //setContentView(R.layout.activity_main); //RN中不需要此处填充view 使用解析到的JS端的view填充
    initRNRootView();//初始化RN的rootView,所有解析到的view都按规则添加到该View上
    //打开悬浮窗(overlay)权限
    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);
        }
    }
}

private void initRNRootView() {
    mReactRootView = new ReactRootView(this);
    mReactInstanceManager = ReactInstanceManager.builder().setApplication(getApplication())
            .setBundleAssetName("index.android.jsbundle")//main.jsbundle
            .setJSMainModuleName("index.android")//index.android
            .addPackage(new MainReactPackage())
            .setUseDeveloperSupport(BuildConfig.DEBUG)//BuildConfig.DEBUG 直接用debug 出现crash ---http://blog.csdn.net/guxiao1201/article/details/50899136
            .setInitialLifecycleState(LifecycleState.RESUMED)
            .build();
    mReactRootView.startReactApplication(mReactInstanceManager, "RNFirstComponent", null);
    setContentView(mReactRootView);
}

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

@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() {
    if (mReactInstanceManager != null) {
        mReactInstanceManager.onBackPressed();
    } else {
        super.onBackPressed();
    }
}

@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
    if (mReactInstanceManager != null && keyCode == KeyEvent.KEYCODE_MENU) {
        mReactInstanceManager.showDevOptionsDialog();
        return true;
    }
    return super.onKeyUp(keyCode, event);
}
//打开悬浮窗(overlay)权限
@Override
protected 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...
                Log.d(TAG, "onActivityResult: ");
            }
        }
    }
}
}

需要把其中一段代码拿出来说:
RN入门---环境搭建和第一个RN项目_第4张图片

js端代码

import React from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View
} from 'react-native';

class HelloWorld extends React.Component {
  render() {
    return (
      
        Hello, World
      
    )
  }
}
var styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
  },
  hello: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
});

AppRegistry.registerComponent('RNFirstComponent', () => HelloWorld);//名字必须和上图android端请求的一致

四、另:

1、当nodejs服务端启动不起来时,停留在下图所示:
RN入门---环境搭建和第一个RN项目_第5张图片
此时需要通过命令行生成离线bundle。

2、 手动生成bundle文件,需要我们执行如下命令:

react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output app/src/main/assets/index.android.bundle --assets-dest app/src/main/res/

RN入门---环境搭建和第一个RN项目_第6张图片

3、React Native项目在64位Android手机上运行,会提示
“/data/data/com.xxx.xxx/lib-main/libgnustl_shared.so” is 32-bit instead of 64-bit 这个错误。
解决方法就是取消掉所有的64位的.so文件,全部加载32位的就可以了,下面是步骤
a、在项目的根目录的 gradle.properties 里面添加一行代码 android.useDeprecatedNdk=true.
b、在 build.gradle 文件里添加以下代码

android {  
    ...  
    defaultConfig {  
        ...  
        ndk {  
            abiFilters "armeabi-v7a", "x86"  
        }  

        packagingOptions {  
            exclude "lib/arm64-v8a/librealm-jni.so"  
        }  
    }  
}  

4、可以通过数据线和服务端连接即时拿取bundle文件;也可通过wifi和服务端连接即时拿取bundle文件(要求手机和电脑在同一个wifi下);也可以通过命令直接生成离线bundle。

5、服务端执行npm start 窗口会显示打包bundle的进度如下
RN入门---环境搭建和第一个RN项目_第7张图片


五、参考:

http://reactnative.cn/docs/0.50/integration-with-existing-apps.html#content
http://blog.csdn.net/chichengjunma/article/details/53815299
http://m.blog.csdn.net/M075097/article/details/76551415

你可能感兴趣的:(Android第三方)