React Native入门及一些踩过的坑

 

集成步骤也可以参考react-native中文网,但是中间还是会遇到特殊情况,上面没有说明

一、安装node(不然npm的时候会报“不是内部命令”)

  npm是nodejs的一个子内容,所以要使用npm,就一定要先安装nodejs。安装方法其实没啥好说的,完全傻瓜化的,官网上下载安装包,一路next就完了。

  安装完了如何判断自己是否安装成功呢?

  你只需要在命令行窗口中输入命令:  

node -v    //查看node 的版本号

npm -v   //查看npm的版本号

二、安装react-native

执行以下命令,进行安装

npm install -g react-native-cli

三、创建package.json

在项目根目录下创建一个名为package.json。可以直接创建,也可以使用npm init创建

{
  "name": "MyRNTest",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "start": "node node_modules/react-native/local-cli/cli.js start",
    "test": "jest"
  },
  "dependencies": {
    "babel-preset-react-native": "^4.0.0",
    "react": "^16.0.0-alpha.6",
    "react-native": "^0.55.0",
    "react-native-update": "^4.0.6"
  },
  "devDependencies": {
    "babel-jest": "21.2.0",
    "jest": "21.2.1",
    "react-test-renderer": "16.0.0-alpha.6"
  },
  "jest": {
    "preset": "react-native"
  }
}

四、配置 maven

在项目的 build.gradle 文件中为 React Native 添加一个 maven 依赖的入口,必须写在 "allprojects" 代码块中:

allprojects {
    repositories {
        maven {
            //url "$rootDir/node_modules/react-native/android"如果路径这样写,会下载最新版本RN
            url "$rootDir/../node_modules/react-native/android"
        }
        ...
    }
    ...
}

在你的 app 中 build.gradle 文件中添加 React Native 依赖

dependencies {
    implementation 'com.android.support:appcompat-v7:27.1.1'
    ...
    //如果要限制版本:implementation("com.facebook.react:react-native:0.55.0") { force = true }
    implementation "com.facebook.react:react-native:+" 
}
defaultConfig {
        ...

        ndk {
            abiFilters "armeabi-v7a", "x86"
        }

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

    //解决jsr302与jsr305版本冲突
    configurations.all {
        resolutionStrategy.force 'com.google.code.findbugs:jsr305:1.3.9'
    }

五、配置权限

在 AndroidManifest.xml 清单文件中声明权限:

//网络权限
<uses-permission android:name="android.permission.INTERNET" />
//弹框权限
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

 

如果需要访问 DevSettingsActivity 界面(即开发者菜单),则还需要在 AndroidManifest.xml 中声明:

<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />

六、RN组件

1.首先在项目根目录中创建一个空的index.js文件。(注意在 0.49 版本之前是 index.android.js 文件)

index.js是 React Native 应用在 Android 上的入口文件。而且它是不可或缺的!

2. 添加你自己的 React Native 代码,简单例子,网上都有,我这里举一个多入口引用的例子

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

import MyFirstRN from './myfirstrn'//填写对应myfirstrn.js路径,我这里在根目录下
import MySecondRN from './mysecondrn'//填写对应mysecondrn.js路径,我这里在根目录下

//注册:第一个字段可以认为是为RN中的页面添加映射,需要和你Activity中注册的名称一致
AppRegistry.registerComponent('MyRNActivity', () => MyFirstRN);
AppRegistry.registerComponent('MyRNActivity2', () => MySecondRN);

注意,一个RN页面只能对应注册一个名称,不然会被覆盖,例如:

AppRegistry.registerComponent('MyRNActivity', () => MyFirstRN);
AppRegistry.registerComponent('MyRNActivity2', () => MyFirstRN);
//此时,MyRNActivity2会对应MyFirstRN,MyRNActivity不会对应,你的Activity中如果注册MyRNActivity
//则会报红屏MyRNActivity未注册

myfirstrn.js和mysecondrn.js简单写了下,需要注意里面的class需要用export default修饰,不然import时会报错

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

export default class MyFirstRN extends Component {
  render() {
      return (
        <View >
          <Text >
            我是 MyFirstRN ReactNative//例子里MySecondRN就这里改了下
          </Text>
        </View>
      );
    }
  }

七、悬浮框权限(仅开发时用于看红屏报错)

如果你的应用会运行在 Android 6.0(API level 23)或更高版本,请确保你在开发版本中有打开悬浮窗(overlay)权限。你可以在代码中使用Settings.canDrawOverlays(this);来检查。之所以需要这一权限,是因为我们会把开发中的报错显示在悬浮窗中(仅在开发阶段需要)。在 Android 6.0(API level 23)中用户需要手动同意授权。具体请求授权的做法是在onCreate()中添加如下代码。其中OVERLAY_PERMISSION_REQ_CODE是用于回传授权结果的字段。

private final int OVERLAY_PERMISSION_REQ_CODE = 1;  // 任写一个值

...

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);
    }
}
@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
            }
        }
    }
    mReactInstanceManager.onActivityResult( this, requestCode, resultCode, data );
}

八、调用RN页面

有两种方法:

1.你的Activity继承ReactActivity

public class MyRNActivity2 extends ReactActivity {
//public class MyRNActivity2 extends BaseReactActivity {
    @Nullable
    @Override
    protected String getMainComponentName() {
        return "MyRNActivity2";
    }
}

2.你的Activity实现 DefaultHardwareBackBtnHandler 接口

public class MyRNActivity 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())

                .setCurrentActivity(this)

                .setBundleAssetName("index.android.bundle")

                .setJSMainModulePath("index.android")//xxx.js
                .addPackage(new MainReactPackage())

                .setUseDeveloperSupport(true)

                .setInitialLifecycleState(LifecycleState.RESUMED)

                .build();

        // 注意这里的MyReactNativeApp必须对应“index.android.js”中的
        // “AppRegistry.registerComponent()”的第一个参数
        mReactRootView.startReactApplication(mReactInstanceManager, "MyRNActivity", null);
        setContentView(mReactRootView);
    }

    @Override
    public void invokeDefaultOnBackPressed() {
        if(mReactInstanceManager!=null){
            mReactInstanceManager.onBackPressed();
        }else{
            super.onBackPressed();
        }
    }
    @Override
    protected void onResume() {
        super.onResume();
        if(mReactInstanceManager!=null){
            mReactInstanceManager.onHostResume(this,this);
        }

    }


    @Override
    protected void onPause() {
        super.onPause();

        if(mReactInstanceManager!=null){
            mReactInstanceManager.onHostPause(this);
        }
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();

        if(mReactInstanceManager!=null){
            mReactInstanceManager.onHostDestroy(this);
        }
    }

}

另外:如果是原生和RN混合页面,可以在布局中添加RN控件,在activity中findview出来

<com.facebook.react.ReactRootView
    android:id="@+id/test_js2"
    ....
/>
public class MyRNActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler {

    private ReactRootView mReactRootView,mReactRootView2;

    private ReactInstanceManager mReactInstanceManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my_rn);

        mReactRootView = findViewById(R.id.test_js);
        mReactInstanceManager = ReactInstanceManager.builder()

                .setApplication(getApplication())

                .setCurrentActivity(this)//可以不需要此代码

                .setBundleAssetName("index.android.bundle")

                .setJSMainModulePath("index.android")//xxx.js
                .addPackage(new MainReactPackage())

                .setUseDeveloperSupport(true)

                .setInitialLifecycleState(LifecycleState.RESUMED)

                .build();

        // 注意这里的MyReactNativeApp必须对应“index.android.js”中的
        // “AppRegistry.registerComponent()”的第一个参数
        mReactRootView.startReactApplication(mReactInstanceManager, "MyRNActivity", null);

    }

    @Override
    public void invokeDefaultOnBackPressed() {
        if(mReactInstanceManager!=null){
            mReactInstanceManager.onBackPressed();
        }else{
            super.onBackPressed();
        }
    }
    @Override
    protected void onResume() {
        super.onResume();
        if(mReactInstanceManager!=null){
            mReactInstanceManager.onHostResume(this,this);
        }

    }


    @Override
    protected void onPause() {
        super.onPause();

        if(mReactInstanceManager!=null){
            mReactInstanceManager.onHostPause(this);
        }
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();

        if(mReactInstanceManager!=null){
            mReactInstanceManager.onHostDestroy(this);
        }
    }

}

九、Application继承ReactApplication

public class MyApp extends Application implements ReactApplication {

    private ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {

        @Override
        public boolean getUseDeveloperSupport() {
            return true;
        }

        @Override
        protected String getJSMainModuleName() {
            return "index.android";
        }

        @Override
        protected List<ReactPackage> getPackages() {
            return Arrays.<ReactPackage>asList(
                    new MainReactPackage()
            );
        }};

        @Override
        public ReactNativeHost getReactNativeHost() {
            return mReactNativeHost;
        }

        @Override
        public void onCreate() {
            super.onCreate();
            SoLoader.init(this,false);
        }
}

十、生成.bundle和.map文件

在app/main下创建assets文件夹,然后Android Studio Terminal在执行。0.49之后的版本index.android.js用index.js

$ react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output app/src/main/assets/index.android.b
undle --assets-dest app/src/main/res/
>npm start

十一、一些坑

1.RN页面首次加载时,会白屏一下,可以采用 预加载 的方法

2.调试时请确保电脑和手机在同一WiFi环境下,不要使用WiFi共享类的软件,那可能导致APP红屏报404

3.红屏报错调用不到.so文件,app目录下的build.gradle中没有添加ndk {abiFilters "armeabi-v7a", "x86"}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值