• ReactNative实战


    ReactNative实战

    一、环境准备

    注*:下面习惯将ReactNative简称为RN

    详细步骤可参见 -> RN环境搭建

    nodeyarn,开发工具android studiovscode

    需要用到react-native脚手架搭建项目,yarn global add react-native

    创建RN项目,react-native init app-demo,可以看到当前项目生成了一个app-demo目录,里面有android目录和ios目录,分别表示android开发和ios开发的,因为RN实际上只是是跨平台的UI库,大多数涉及到系统开发的逻辑需要通过与原声交互的方式实现

    通过命令行进入app-demo目录,使用yarn install下载依赖,命令会检索package.json文件中的dependenciesdevDependencies节点的依赖下载到当前目录的node-modules文件夹下

    常见问题(一)

    直接启动RN项目在下载android相关依赖时可能会因为网络问题导致下载包失败

    设置android依赖设置为国内镜像,提高下载速度,打开android目录,编辑build.gradle

    // Top-level build file where you can add configuration options common to all sub-projects/modules.
    
    buildscript {
        ext {
            buildToolsVersion = "28.0.3"
            minSdkVersion = 16
            compileSdkVersion = 28
            targetSdkVersion = 28
            // googlePlayServicesVersion = "16.1.0" // default: "16.1.0" - pre-AndroidX, override for AndroidX
        }
        repositories {
            // google()
            // jcenter()
            
            // 替换成国内镜像源
            maven { url 'https://maven.aliyun.com/repository/jcenter' }
            maven { url 'https://maven.aliyun.com/repository/google' }
        }
        dependencies {
            classpath('com.android.tools.build:gradle:3.5.2')
    
            // NOTE: Do not place your application dependencies here; they belong
            // in the individual module build.gradle files
        }
    }
    
    allprojects {
        repositories {
            // 先本地maven仓库中找
            mavenLocal()
            maven {
                // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
                url("$rootDir/../node_modules/react-native/android")
            }
            maven {
                // Android JSC is installed from npm
                url("$rootDir/../node_modules/jsc-android/dist")
            }
    
            maven { url 'https://maven.aliyun.com/repository/jcenter' }
            maven { url 'https://maven.aliyun.com/repository/google' }
            maven { url 'https://jitpack.io' }
    
            // google()
        }
    }
    
    常见问题(二)

    这样直接运行RN项目可能会遇上一个奇怪的bug,页面直接报错,Cannot find entry file index.android.js in any of the roots,原因是RN默认是去找index.android.js这个文件,而初始化的RN项目的入口文件名叫index.js,所以需要修改android/app/build.gradle

    project.ext.react = [
        entryFile: "index.js",
        enableHermes: false,  // clean and rebuild if changing
        bundleInDebug: true
    ]
    
    运行RN项目

    打开package.json文件,找到scripts节点,目前只关心androidstart命令,可通过yarn android运行scripts节点下的命令,相当与间接运行react-native run-android

    "scripts": {
        "android": "react-native run-android",
        "ios": "react-native run-ios",
        "start": "react-native start",
        "test": "jest",
        "lint": "eslint ."
    },
    

    手机进入开发者模式,并设置连接方式为文件传输,运行adb devices命令确保设备已正常运行并连接,运行yarn android安装应用。

    start命令会启动一个守护进程,用来监控app,可以实现app的热更新,通过r键刷新app,d在app上打开调试菜单

    二、ReactNative是什么

    React有着Learn One, Write Any的名号,RN也不例外,它完全可以用React的语法进行编码开发

    对于使用过React的人并不陌生,render函数是React在渲染页面时使用的方法,对于RN来说,render函数也是渲染app页面的重要函数

    但React和RN在render函数中的使用规则有着比较大的区别,就是React在浏览器中使用时,可以在render函数中使用任何标签,例如<div></div>等,而RN中只能使用预定义好的标签,比如<View></View>,在RN中,可以把View标签当作div来用

    之所以不能使用普通的html标签是因为RN和普通的WebView实现的app不一样,它需要保证App的性能,所以需要做一些定制化工作,比如View这些标签实际上在android或ios有着自己原生代码的实现,就拿android来说,RN在实现View标签的时候,在android底层封装了一个active.xml,使用View标签就相当与在底层使用了这个active.xml的布局文件,所以RN的性能并不会和原声Android相差太多

    因为RN的UI组件都是经过原生代码封装过的,所以它无法想WebView那样做到任意的定制化布局,它的想象空间被极大的限制住了。但是RN还是有着自己独特的优点,它能让不熟悉原生android的前端开发人员也能具备开发一些简单的“Curd App”的能力,然并luan!如果想用RN开发出来一款真正的产品,仅仅是写写页面是微不足道的,他离不开原生开发的支持。比如做个百度地图需要用到GPS,登录页的人脸识别需要相机,需要在AndroidManifest.xml文件中配置app所需要的权限,比如接下来我要讲的硬件监控需要读取android系统的/proc/stat(CPU使用情况)或者/proc/meminfo(内存使用情况)等。直接用RN是做不到的,虽然网上有类似的插件(react-native-device-info),但我测试的时候发现获取内存信息和磁盘信息数据量不准确的问题,还有不支持获取cpu和流量信息。

    可以看到,当想要把app真正的作为一款产品来开发的话,绝对是离不开原生开发的支持的,就算RN发展的如火如荼,但不管怎样,毕竟Android和ios才是地头蛇,如果只是一味的想要比较WebView、RN、原声这些app开发技术到底哪个好,最终只会是限制自己的发展

    三、使用RN的第三方插件

    大多数RN的第三方插件也是通过原生代码实现的

    以上面提过的react-native-device-info为例,其它的RN插件引入RN的方式和这个一样,像react-native-fs(文件读写)、react-native-background-timer(后台定时任务,虽然用RN的Headless也可以实现)这些插件,能提高我们的开发效率,当然,如果经历允许的话,也可以自己编写插件并发布到网上。

    参考 react-native-device-info使用

    可能插件官方的教程适用于旧版RN,对于我0.61.5较新的版本来说,需要稍作改动

    1. yarn add react-native-device-info

    2. 修改android/settings.gradle,添加

      include ':react-native-device-info'
      project(':react-native-device-info').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-device-info/android')
      
    3. 修改android/app/build.gradle,在dependencies节点添加

      implementation project(':react-native-device-info')
      

    然后就可以直接在js上使用了

    四、RN与原生交互

    创建一个简单的工具类,然自己可以通过js调用android的代码,工具类需要继承ReactContextBaseJavaModule并实现getName方法,getName方法返回的字符串就是工具类的标识

    下面定义的toastMsg方法接收js传过来的参数字符串并将参数作为提示弹出到app页面上

    提供给js调用的方法需要加上@ReactMethod注解

    在js中可以通过NativeModules.ToastExample.toastMsg("提示")这种方法调用

    public class ToastModule extends ReactContextBaseJavaModule {
    
        public ToastModule(ReactApplicationContext reactContext) {
            super(reactContext);
        }
    
        @NonNull
        @Override
        public String getName() {
            return "ToastExample";
        }
    
        /**
         * 弹出一个提示
         */
        @ReactMethod
        public void toastMsg(String msg) {
            Toast.makeText(getReactApplicationContext(), msg, Toast.LENGTH_SHORT).show();
        }
    }
    

    第二步,还需要将自定义的工具类注册一下,再创建个自定义的包管理器,实现ReactPackage接口

    public class AnExampleReactPackage implements ReactPackage {
    
        @Override
        public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
            return Collections.emptyList();
        }
        @Override
        public List<NativeModule> createNativeModules(
                ReactApplicationContext reactContext) {
            List<NativeModule> modules = new ArrayList<>();
            // 将刚刚的工具类放上去
            modules.add(new ToastModule(reactContext));
            return modules;
        }
    }
    

    第三步,修改MainApplication.java文件,在ReactNativeHost内部类实现的getPackages方法中加上刚刚的自定义包管理器

    private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
        @Override
        public boolean getUseDeveloperSupport() {
            return BuildConfig.DEBUG;
        }
    
        @Override
        protected List<ReactPackage> getPackages() {
            @SuppressWarnings("UnnecessaryLocalVariable")
            List<ReactPackage> packages = new PackageList(this).getPackages();
            // 将自定义包管理器放进去
            packages.add(new AnExampleReactPackage());
            // Packages that cannot be autolinked yet can be added manually here, for example:
            // packages.add(new MyReactNativePackage());
            return packages;
        }
    
        @Override
        protected String getJSMainModuleName() {
            return "index";
        }
    };
    

    大功告成!

  • 相关阅读:
    拉姆达表达式(lambda Expressions)
    Func,Action 的介绍
    VS2012 此模板尝试加载组件程序集”NuGet.VisualStudio.interop,Version=1.0.0.0 的解决
    444 英语口语
    Base algorithm
    Windows Search Service
    Windows Azure Storage
    HDU 3395 Special Fish
    CodeForces 235B Let's Play Osu!
    HDU 3435 A new Graph Game
  • 原文地址:https://www.cnblogs.com/dagger9527/p/12734829.html
Copyright © 2020-2023  润新知