React-Native for Android

本文介绍了React-Native在Android平台的应用,强调了其提供原生用户体验和React开发效率的优势。详细阐述了环境配置,包括工具和SDK要求,并演示了Hello World示例。接着讲解了React Native组件、生命周期、数据管理以及布局。Android Studio工程和打包发布过程也有所涉及,特别是react-native-gradle插件用于Android应用的打包配置。
摘要由CSDN通过智能技术生成

React-Native Android

既拥有Native的用户体验、又保留React的开发效率。

  尽管Native开发成本更高,但现阶段Native仍然是必须的,因为Web的用户体验仍无法超越Native:
  ① Native的原生控件有更好的体验;
  ② Native有更好的手势识别;
  ③ Native有更合适的线程模型,尽管Web Worker可以解决一部分问题,但如图像解码、文本渲染仍无法多线程渲染,这影响了Web的流畅性。
  ④ Native能实现更丰富细腻的动画效果,归根结底是现阶段Native具有更好的人机交互体验

React Native
图片来自天猫技术:
天猫技术–关于React-Native

1.环境

  React Native只支持在OS X系统, React Native开发的app 要求客户端os >= Android 4.1 (API 16) 和>= iOS 7.0

1.1 工具
  • Homebrew
  • Nodejs
  • nvm
  • watchman
  • flow
1.2 SDK 环境要求
  • Android SDK Build-tools version 23.0.1
  • Android 6.0 (API 23)
  • Android Support Repository
1.3 Demo Hello World
$ npm install -g react-native-cli
$ react-native init AwesomeProject
$ cd AwesomeProject/
$ react-native run-android

  相应的会在目录AwesomeProject/android/app下创建Android Studio工程,AwesomeProject/iOS/AwesomeProject.xcodeproj目录中创建XCode工程

注:不管是 iOS 还是 Android,在开发调试阶段,都需要在 Mac 上启动一个 HTTP 服务,称为Debug Server,默认运行在 8081 端口,APP 通 Debug Server 加载 js。

2.概念

2.1 Component组件

  React Native 主要是通过 Virtual Dom 来实现显示页面或者页面中的模块。可以通过 React.createClass() 来创建自己的 Dom,在 React 中称之为组件(Component)

1. 创建组件
    // Android
    var React = require('react-native');
    var { DrawerLayoutAndroid, ProgressBarAndroid } = React;

    var App = React.createClass({
        render: function() {
            return (
                <DrawerLayoutAndroid
                    renderNavigationView={() => <Text>React Native</Text>}>
                    <ProgressBarAndroid />
                </DrawerLayoutAndroid>
            );
        },
    });

    // iOS
    var React = require('react-native');
    var { TabBarIOS, NavigatorIOS } = React;

    var App = React.createClass({
        render: function() {
            return (
                <TabBarIOS>
                    <TabBarIOS.Item title="React Native" selected={true}>
                        <NavigatorIOS initialRoute={{ title: 'React Native' }} />
                    </TabBarIOS.Item>
                </TabBarIOS>
            );
        },
    });
2. 使用组件

  类似 HTML 标准标签
<< MyCustomComponent />

<< MyCustomComponent >
<< /MyCustomComponent>

3. 组件生命周期

  React 组件的数据保存在自己内部的 state 变量中.都有相应回调。
- getInitialState: 获得初始化组件状态,只调用一次.
- componentWillMount: 组件将要加载,只调用一次
- componentDidMount: 组件加载完成并显示出来了,也就是完成了一次绘制,只调用一次
- render: 绘制组件,可能调用多次。
  

4. 自定义组件

  render 函数是必须的,其他可选

var MyCustomComponent = React.createClass({

    getInitialState: function() {
        // 这里返回一个对象,设置组件的初始化状态,后面就可以通过 this.state 来获得这个对象
        return {
            key1: data1,
            key2: data2,
            ...
        };
    },

    componentWillMount: function() {
        // 这里一般做一些和界面显示无关的初始化操作
    },

    componentDidMount: function() {
        // 这里一般做加载数据的操作
    },

    render: function() {
        // 这是最重要的函数,用来绘制界面,所有的自定义组件,这个函数是必须提供的
        return(
            <View>
                ...
            </View>
        );
    },
});
5. 组件数据

  根据组件的状态 state 来绘制动态页面

render: function() {
    return(
        //把状态中的 key1 的值用 Text 组件直接显示
        <Text>{this.state.key1}</Text>
    );
}
状态(statu)

  组件的状态(statu) 除了使用 getInitialState 方法来设置初始化状态外,在界面逻辑处理或者事件交互的过程中,
可以调用 this.setState(…) 方法来修改组件的状态值。如果在代码中直接修改 state,React 就会把旧状态和新状态
做一个 diff,找到变化的部分,然后对应找到和这个变化的值关联的界面部分,请求重新绘制这个部分。

属性(Property)

  属性(Property)可以通过 this.props 来直接获取

<View style={{flex: 1}}>

   区别: 一般 属性 表示静态的数据,组件创建后,就基本不变的内容,状态 是动态数据。

3.React Native布局

  React Native 的布局,实用的是 FlexBox 实现,类似网页的 CSS 布局方法

React Native 中的样式长度单位,是逻辑单位,概念和 Android 中的 dp 一样。

示例Demo: 知乎日报客户端
github源码地址

4.Android Studio示例工程概览

   MainActivity 已经针对React Native做了一层封装调用,默认帮我们维护了React Native的生命周期。

import android.app.Activity;
import android.os.Bundle;
import android.view.KeyEvent;

import com.facebook.react.LifecycleState;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactRootView;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;

public class MainActivity extends Activity implements DefaultHardwareBackBtnHandler {

    private ReactInstanceManager mReactInstanceManager;
    private ReactRootView mReactRootView;

    @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();

        mReactRootView.startReactApplication(mReactInstanceManager, "AwesomeProject", null);

        setContentView(mReactRootView);
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
            mReactInstanceManager.showDevOptionsDialog();
            return true;
        }
        return super.onKeyUp(keyCode, event);
    }

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

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

        if (mReactInstanceManager != null) {
            mReactInstanceManager.onPause();
        }
    }

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

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

   index.android.js

**
 * Sample React Native App
 * https://github.com/facebook/react-native
 */
'use strict';

var React = require('react-native');
var {
  AppRegistry,
  StyleSheet,
  Text,
  View,
} = React;

var AwesomeProject = React.createClass({
  render: function() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>
          Welcome to React Native!
        </Text>
        <Text style={styles.instructions}>
          To get started, edit index.android.js
        </Text>
        <Text style={styles.instructions}>
          Shake or press menu button for dev menu
        </Text>
      </View>
    );
  }
});

var styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});

AppRegistry.registerComponent('AwesomeProject', () => AwesomeProject);

   package.json 是工程的依赖和元数据配置文件:

{
  "name": "AwesomeProject",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node_modules/react-native/packager/packager.sh"
  },
  "dependencies": {
    "react-native": "^0.11.0"
  }
}

5.打包发布独立安装包

开发调试的时候必须启动个 JS Server,然后要让手机连接这个 Server。React Native 应用打包的时候,会连接 JS Server 下载一个 ReactNativeDevBundle.js 文件,然后放到应用数据的 files 目录下,就能运行这个 JS 文件了

  目前 iOS 应用可用 react-native bundle 命令进行打包,android暂时没有支持。
针对 Android 的 React Native 应用,可用 react-native-gradle 插件进行打包。该插件灵活配置打包参数,使用 Gradle Task 将资源打包到资源文件夹。

5.1 react-native-gradle 插件

  借助插件 react-native-gradle:com.facebook.react:gradleplugin:1.0.+ 可完成混淆及资源打包。(插件并没有发布到 JCenter 或者 Maven Centry)插件源码github地址

安装: react-native-gradle srain$ gradle install

项目中使用build.gradle配置:

buildscript {
    repositories {
        mavenLocal()    // 本地依赖
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.3.0'
        classpath 'com.facebook.react:gradleplugin:1.0.+'   // 插件依赖
    }
}

app/build.gradle配置:

apply plugin: 'com.facebook.react'

react {
    bundleFileName "index.android.bundle"   // assets 目录下 js 文件名
    bundlePath "/index.android.bundle"      // js 路径
    jsRoot "../"                            // js 源文件位置
    packagerHost "localhost:8081"           // debug server 地址
    packagerCommand "./node_modules/react-native/packager/packager.sh"  // 打包命令地址

    devParams {
        skip true
        dev true
        inlineSourceMap false
        minify false
        runModule true
    }
    releaseParams {
        skip false
        dev false
        inlineSourceMap false
        minify true
        runModule true
    }
}
Params参数:


  • skip 是否跳过从本地资源加载,从 Debug Server 请求资源
    其他四个参数通过 url 传给 Debug Server。
    • dev: 全局变量 DEV, React Native 核心类库的开发选项
    • minify: 混淆
    • inlineSourceMap: 是否加入 source map。默认 false
    • runModule: 是否在最后以 require(XXX) 的形式加入 module 的入口点。默认 true

require(“AwesomeProject/index.android.js”);
官网地址:https://facebook.github.io/react-native/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值