Android react native 开发入门

react、react native、webStorm、vscode介绍

1、react是facebook开源的一套申明式js前端框架,React 是基础框架,是一套基础设计实现理念,开发者不能直接使用它来开发移动应用或者网页,发展出了React.js 框架来开发网页
2、react native是在React框架之上,用前端的技术将jsx通过babel编译成reactElement,在创建对应的原生组件在移动端运行的app,性能比原生应用差

react native 环境配置

参考教程
face book官方建议使用Chocolatey安装Python2nodejs

安装Chocolatey

管理员身份打开windowns的CMD,输入

@"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"  

安装nodejs、python

重新打开一个cmd窗口,输入安装指令

choco install -y nodejs.install python2  

安装React Native命令行界面

npm install -g react-native-cli

Android开发环境配置(略)

创建RN项目

AwesomeProject为工程名,按实际情况自定义,输入指令后一直确定即可

react-native init AwesomeProject

编译Android项目

检查是否配置成功,故障排查

cd AwesomeProject  
react-native run-android  

 

react native 集成到现有android工程

参考资料

设置目录结构(可跳过)

为确保顺畅体验,请为集成的React Native项目创建新文件夹,然后将现有Android项目复制到/android子文件夹

配置package.json

工程根目录下新建package.json文件,输入内容

{
  "name": "MyReactNativeApp",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "yarn react-native start"
  }
}

安装react和react-native包

工程根目录下打开终端,依次输入

yarn add react-native  
yarn add react@version_printed_above  

 

集成React Native到Android工程

按照此配置如果不能成功点亮工程,可以逆向思维,将android工程直接拷贝到RN工程的android目录,反向操作实现集成
添加依赖

implementation "com.facebook.react:react-native:+"

配置maven

maven {
    // All of React Native (JS, Android binaries) is installed from npm
    //设置目录机构时将android工程移到android文件夹时使用此路径,否则使用下面的路径
    url "$rootDir/../node_modules/react-native/android"
    // url "$rootDir/node_modules/react-native/android" //
}

配置AndroidManifest

<uses-permission android:name="android.permission.INTERNET" />  
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />  

配置Application和activity

1、新建RNPageActivity继承ReactActivity,getMainComponentName方法返回值与package.json中的name标签值相同

class RNPageActivity : ReactActivity() {
    override fun getMainComponentName(): String {
        return "MyReactNativeApp"
    }
}

2、Application实现接口ReactApplication重写getReactNativeHost方法

class MyApp : BaseApplication(), ReactApplication {
    override fun onCreate() {
        super.onCreate()
        SoLoader.init(this, false)
    }

    override fun getReactNativeHost(): ReactNativeHost {
        return mReactNativeHost
    }

    private val mReactNativeHost = object : ReactNativeHost(this) {

        override fun getUseDeveloperSupport(): Boolean {
            return com.topband.base.BuildConfig.DEBUG
        }

        override fun getPackages(): List<ReactPackage> {
            //此处配置RN与原生通信模块
            return listOf<ReactPackage>(
                MainReactPackage()
            )
        }

        override fun getJSMainModuleName(): String {
            return "index"
        }
    }
}

测试您的集成

1、工程根目录新建index.js文件,输入内容
MyReactNativeApp对应package.json中的name

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

class HelloWorld extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.hello}>Hello, World</Text>
      </View>
    );
  }
}
var styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
  },
  hello: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
});
AppRegistry.registerComponent('MyReactNativeApp', () => HelloWorld);  

2、项目根目录打开终端输入指令启动服务后

 yarn start

3、正常构建并运行您的Android应用,正常情况会看到终端提示服务启动成功,编译后的app启动RNPageActivity能加载RN界面显示“Hello, World”

 

Android与RN相互通信

官方文档

创建ReactContextBaseJavaModule子类

将需要暴露接口的原生类继承ReactContextBaseJavaModule

public class TestNative extends ReactContextBaseJavaModule {
    public TestNative(@Nonnull ReactApplicationContext reactContext) {
        super(reactContext);
    }

    @Nonnull
    @Override
    public String getName() {
        //暴露给js的名称,js通过名称找到本类
        return "test";
    }
}

注解标记方法

使用@ReactMethod注解标记方法

@ReactMethod
public void test(int data, Callback callback) {
    // todo
    callback.invoke("这里可以回调到RN");
}

创建ReactPackage子类

新建一个类实现ReactPackage接口,重写createNativeModules方法,将需要注册的本地模块添加进去

public class TestPackages implements ReactPackage {
    @Nonnull
    @Override
    public List<NativeModule> createNativeModules(@Nonnull ReactApplicationContext reactContext) {
        //将需要注册的本地模块添加到list返回
        List<NativeModule> list = new ArrayList<>();
        list.add(new TestNative(reactContext));
        return list;
    }
}  

配置的Application

前面配置的Application中找到getPackages方法,将TestPackages返回

@Override
protected List<ReactPackage> getPackages() {
    @SuppressWarnings("UnnecessaryLocalVariable")
    List<ReactPackage> packages = new PackageList(this).getPackages();
    //这里将TestPackages添加进去
    packages.add(new TestPackages());
    return packages;
}

RN页面使用原生接口

//导入NativeModules
import {  NativeModules  } from 'react-native';  

//找到原生模块,此处的test与TestNative类中getName方法返回的值一致
const testNative = NativeModules.test;
//调用原生方法
testNative.test(111,  function (e) {  
    // todo 
})

支持的参数类型

java类型js类型
BooleanBool
IntegerNumber
DoubleNumber
FloatNumber
StringString
Callbackfunction
ReadableMapObject
ReadableArrayArray

原生主动发送事件到JavaScript

androi原生发送事件是通过ReactApplicationContext完成。eventName为自定义名称,原生与js层保持一致即可。可以通过不同的eventName定义多种类型事件。事件发送ios和android有部分差异,可以查阅官方关于iso事件发送或者咨询ios开发

 mReactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("eventName", params);  

RN界面注册事件监听

   DeviceEventEmitter.addListener('eventName', function(data){

   });

RN使用原生View

官方文档

创建ViewManager子类

以TextView举例,新建ReactTextManager继承SimpleViewManager

public class ReactTextManager extends SimpleViewManager<TextView> {

    @Nonnull
    @Override
    public String getName() {
        //注册名称,js端通过此名称找到本类
        return "testTextView";
    }
}

重写方法 createViewInstance

ReactTextManager类中重写createViewInstance方法,实例化一个TextView

@Nonnull
@Override
protected TextView createViewInstance(@Nonnull ThemedReactContext reactContext) {
    //实例化TextView
    TextView textView = new TextView(reactContext);
    textView.setTextColor(0xffff0000);
    textView.setTextSize(20);
    return textView;
}

使用@ReactProp(或@ReactPropGroup)注解

定义一个setText方法,@ReactProp注解标记后js层可以通过name设置的值直接调用此方法

@ReactProp(name = "text")
public void setText(TextView textView, String text) {
    //暴露setText方法
    Log.i("test", "setText:" + text);
    if (textView != null) {
        textView.setText(text);
    }
}

注册 ViewManager

创建ReactPackage子类,重写createViewManagers方法,实例化ReactTextManager并返回

@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
    List<ViewManager> views = new ArrayList<>();
    views.add(new ReactTextManager());
    return views;
}

JavaScript中使用原生view

导入requireNativeComponent模块

import { requireNativeComponent } from 'react-native';

利用requireNativeComponent找到testTextView,名称为ReactTextManager中getName方法返回的值

const testTextView = requireNativeComponent('testTextView');  

使用testTextView。代码中text="22323"表示调用ReactTextManager类中被@ReactProp(name = "text")注解的方法setText,第一个参数TextView会自动传递一个TextView实例,第二个字符串参数为我们设置的值“22323”

<testTextView text="22323" style={{backgroundColor: '#ffffff', width: 120, height: 50}}/>

开始开发RN

后面的讲述基于RN工程配置成功,能正常编译运行
1、导包,一般情况要导入React、StyleSheet(样式)和需要使用的UI标签、其它扩展库、自己的js库

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

2、继承React.Component

export default class 类命 extends React.Component {

}

3、重写render方法
注意,return返回的内容用括号包裹,举例中的View标签可以替换为其它标签

render(): React.ReactNode {
    return (
        <View > 

        </View> 
   )
}

4、编写Style样式
使用React Native,您不会使用特殊语言或语法来定义样式。只需使用JavaScript设置应用程序的样式。RN中一个标签可以使用多个style修饰,多个style直接继承并扩展,例如 定义pageBg,pageBg2

const styles = StyleSheet.create({
    pageBg: {
        flex: 1,
    },
    pageBg2: {
        backgroundColor: '#eff2f7',
    },
}

使用style,此时View标签样式为flex: 1 并且 backgroundColor: '#eff2f7'

<View style={styles.pageBg , styles.pageBg2 }>  

</View>  

也可以直接在标识上写style,两种方式等同

<View style={{ flex: 1}, {backgroundColor: '#eff2f7' }}> 

</View>  

5、可变属性state
RN控制组件有两种类型的数据:props和state。props由父项设置,props的值在组件的整个生命周期内都是固定的。state需要在constructor方法中定义,state在当前界面修,每次调用setState都会重新执行 render 方法渲染界面。setState 是一个合并操作,每次操作只修改指定属性,不影响其他属性,注意setState 是异步操作,修改不会马上生效

constructor(props) {
    super(props);
    this.state = { next: false },
    };
}

使用、修改

//使用
this.state.xxx  
//修改
this.setState(previousState => {
    return { xxx: !previousState.xxx };
  })

6、不可变属性props
this.props.maxLength RN控制组件有两种类型的数据:props和state。props由父项设置,props的值在组件的整个生命周期内都是固定的

this.props.xxx

配置界面导航(选配)

需要使用界面跳转必须配置,单页面无需配置
FB官方文档
React Native Navigation
1、安装依赖

npm install --save react-navigation  
yarn add react-native-gesture-handler
yarn add react-navigation-stack

2、配置导航界面 这里的HomeScreen、ProfileScreen为自定义界面,按照实际项目修改

import {createAppContainer} from 'react-navigation';
import {createStackNavigator} from 'react-navigation-stack';

const MainNavigator = createStackNavigator({
  Home: {screen: HomeScreen},
  Profile: {screen: ProfileScreen},
});

const AppNavigator = createAppContainer(MainNavigator);

export default AppNavigator;

3、使用AppNavigator
进行界面跳转之前,我们需要在先在某个界面中返回AppNavigator,RN中的界面跳转实际是自定义导航栈

return (
    <AppNavigator/>
);

4、进行界面跳转
Profile对应步骤2中定义的Profile;{name: 'Jane'}是通过key-value方式向下一个界面传递参数,按照实际情况填写,非必须

navigate('Profile', {name: 'Jane'})}  

navigationOptions配置

此配置在Android和ios的UI均采用原生标题栏,所以android和ios不一致,Android采用的是material design的标题栏
1、在单个界面中配置

static navigationOptions = ({navigation}) => ({
    title: '这是title',
    //title样式
    headerTitleStyle: {
        flex: 1,
        textAlign: 'center',
        color: '#ffffff',
        fontSize: 18,
    },
    //标题栏样式
    headerStyle: {
        backgroundColor: '#2f4f68',
    },
});

2、在导航配置时配置

const MainNavigator = createStackNavigator(
    {
        HomePage: {
            screen: HomePage,
            navigationOptions: {
                header: null
            }
        },
    },
    defaultNavigationOptions: {
      headerBackTitle: null,
      headerTintColor: 'grey'
    }
}

禁用标题栏

static navigationOptions = {
    header: null,
};

Flexbox布局

flexDirection布局的主轴

  • row: 水平轴方向排列
  • column: 竖直轴方向排列,默认是竖直
  • row-reverse:左右反转的水平轴方向排列
  • column-reverse:上下反转的,竖直轴方向排列
  • 官方文档

flex权重

  • 当flex为一个正整数时,组件尺寸会具有弹性,并根据具体的 flex 值来按比例分配
  • 当flex为 0 时,组件尺寸由width和height决定,此时不再具有弹性
  • 当flex为-1 时,组件尺寸一般还是由width和height决定。但是当空间不够时,组件尺寸会收缩到minWidth和minHeight所设定的值
  • 官方文档

justifyContent子元素沿着主轴的排列方式

  • flex-start从头排到尾
  • center居中向两端扩散
  • flex-end从尾排到头
  • space-around居中两端均匀分布
  • space-between头尾两端均匀分布
  • space-evenly均匀分布
  • 官方文档

alignItems 子元素沿着次轴排列方式

  • flex-start次轴从头开始
  • center次轴居中
  • flex-end次轴从尾开始
  • stretch拉伸
  • 区别alignContent,只对多行的item才有效果
  • 对alignSelf属性的值进行自定义则会覆盖父类的AlignItems效果
  • 官方文档
  • 参考图片

alignContent

alignContent的布局效果和alignIems完全一致,alignContent只对多行的item才有效果,而后者对单行、多行都有效
官方文档

alignSelf

alignSelf区别于alignItems的是,alignSelf在item内部定义的,它的默认取值是auto,向上取父类alignItems的值,如果对alignSelf属性的值进行自定义则会覆盖父类的效果
官方文档

其它

其它布局介绍点击传送门

RN常用库

数据存储AsyncStorage

JS实现的react-native-easy-toast

图标组件

RNPolymerPo 是一个基于 React Native 的生活类聚合实战项目,目前由于没有 MAC 设备,所以没有适配 iOS,感兴趣的可以自行适配 app 目录下相关 JS 代码即可。 获取代码与编译调试打包 如下所有步骤及说明均为 React Native Android 的 DIY,涉及命令均为 Ubuntu 环境,Windows 类推即可。 1. 获取代码及模块安装和签名配置 执行如下命令进行代码下载及模块安装: $ git clone https://github.com/yanbober/RNPolymerPo.git $ cd RNPolymerPo $ npm install //如果觉得慢可以先切换到国内 npm 镜像源再执行此命令 配置 Gradle 个人签名路径及属性: //1. 把你个人的签名 my-release-key.keystore 文件(不知道如何生成请自行搜索)放到 RNPolymerPo 工程的 android/app 文件夹下。 //2. 编辑工程的 gradle.properties 文件,添加如下的代码(注意把其中的****替换为你自己相应密码)。 MYAPP_RELEASE_STORE_FILE=my-release-key.keystore MYAPP_RELEASE_KEY_ALIAS=my-key-alias MYAPP_RELEASE_STORE_PASSWORD=***** MYAPP_RELEASE_KEY_PASSWORD=***** 2. 编译打包 APK 文件 编译生成在线快速调试 Debug 开发包,执行如下命令: $ adb reverse tcp:8081 tcp:8081 $ react-native start //开启本地 JS 服务 $ react-native run-android //新终端的 RNPolymerPo 目录下执行 编译生成 release 包,执行如下命令: $ cd android && ./gradlew assembleRelease 拓展规划 下一个版本准备做的事情: 兼容性处理; 夜间模式; 热修复及 PHP 服务端编写; 多语言切换等问题评估;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值