通过上一篇《 React-Native Android 学习笔记——1,配置环境》下载了AwesomeProject项目并运行了 demo。如下图:
应该和你运行起来的相同,但是除了Welcome to React Native
的颜色。
一,index.android.js 文件
demo 默认展示在我们面前的这个页面其实是我们下载AwesomeProject
项目下的index.android.js
,代码如下:
/** * Sample React Native App * https://github.com/facebook/react-native */
'use strict';
import React,{
AppRegistry,Component,StyleSheet,Text,View,} from 'react-native';
class AwesomeProject extends Component {
render() {
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> ); } } const styles = StyleSheet.create({ container: { flex: 1,justifyContent: 'center',alignItems: 'center',backgroundColor: '#F5FCFF',},welcome: { fontSize: 20,textAlign: 'center',margin: 10,color:'red' },instructions: { textAlign: 'center',color: '#333333',marginBottom: 5,}); AppRegistry.registerComponent('AwesomeProject',() => AwesomeProject);
可以看到我在 welcome 的 style 中设置了color:'red'
,让我的Welcome to React Native
变成红色字体的。如下:
welcome: {
fontSize: 20,textAlign: 'center',margin: 10,color:'red'
},
下面我们来熟悉一下index.android.js
这个文件里面的 js 代码都是干什么的。
'use strict'
是启动当前文件的 js 代码的严格模式,可以使当前的 js 更严格的条件下运行。想了解的可以学习这篇文章《Javascript 严格模式详解》。
import React,} from 'react-native';
这段代码类似 java 的 import,把需要引用的 module 引入。
class AwesomeProject extends Component {
render() {
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>
);
}
}
这段代码是渲染当前注册界面的布局,render
方法下的return 就是返回的当前布局。标签内的 style 对应下面这段代码,和 css 很像,等于 Android layout 文件下 view 的标签设置属性。
const styles = StyleSheet.create({
container: {
flex: 1,justifyContent: 'center',alignItems: 'center',backgroundColor: '#F5FCFF',welcome: {
fontSize: 20,color:'red'
},instructions: {
textAlign: 'center',color: '#333333',marginBottom: 5,});
AppRegistry.registerComponent('AwesomeProject',() => AwesomeProject);
上面这段代码把我们 js 文件中的 class AwesomeProject
和我们 Android 项目中 Activity
中getMainComponentName() { return "AwesomeProject"; }
的 Activity关联起来。
二,显示一个 Toast
React-Native 已经把我们常用的模块都已经封装好了,例如 Toast 在../AwesomeProject/node_modules/react-native/Libraries/Components/ToastAndroid/ToastAndroid.android.js
中。
我们来看 ToastAndroid 的源码:
/** * Copyright (c) 2015-present,Facebook,Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ToastAndroid */
'use strict';
var RCTToastAndroid = require('NativeModules').ToastAndroid;
/** * This exposes the native ToastAndroid module as a JS module. This has a function 'show' * which takes the following parameters: * * 1. String message: A string with the text to toast * 2. int duration: The duration of the toast. May be ToastAndroid.SHORT or ToastAndroid.LONG */
var ToastAndroid = {
SHORT: RCTToastAndroid.SHORT,LONG: RCTToastAndroid.LONG,show: function ( message: string,duration: number ): void {
RCTToastAndroid.show(message,duration);
},};
module.exports = ToastAndroid;
我们可以直接在引包当中加入ToastAndroid。如下:
import React,ToastAndroid,} from 'react-native';
下面我们来用 ToastAndroid 弹出一个 Toast。在引包后加入代码ToastAndroid.show('Awesome',ToastAndroid.SHORT);
,下面来摇摆手机调出开发菜单,点击Reload JS
。就会弹出Toast。
我们来分析一下ToastAndroid.android.js
这个 module。
var RCTToastAndroid = require('NativeModules').ToastAndroid;
这里是require
是加载NativeModules
模块,并把 ToastAndroid
赋值给 RCTToastAndroid
。
var ToastAndroid = {
SHORT: RCTToastAndroid.SHORT,};
这段代码,创建一个对象赋值给ToastAndroid
,对象内分别设置了Toast
的 SHORT
,LONG
和show
方法。
module.exports = ToastAndroid;
这里把ToastAndroid
作为当前这个 Module 导出,提供给外部使用。
那么 JS 是如何 Android 代码关联起来的呢?下面我们来看一下Native 的代码。在 Android Studio 中搜索类 ToastModule
,代码如下:
public class ToastModule extends ReactContextBaseJavaModule {
private static final String DURATION_SHORT_KEY = "SHORT";
private static final String DURATION_LONG_KEY = "LONG";
public ToastModule(ReactApplicationContext reactContext) {
super(reactContext);
}
@Override
public String getName() {
return "ToastAndroid";
}
@Override
public Map<String,Object> getConstants() {
final Map<String,Object> constants = MapBuilder.newHashMap();
constants.put(DURATION_SHORT_KEY,Toast.LENGTH_SHORT);
constants.put(DURATION_LONG_KEY,Toast.LENGTH_LONG);
return constants;
}
@ReactMethod
public void show(String message,int duration) {
Toast.makeText(getReactApplicationContext(),message,duration).show();
}
}
这里getName()
方法的返回值对应 JS 中的var RCTToastAndroid = require('NativeModules').ToastAndroid;
结尾处的ToastAndroid
,正如 js 里的请求手机本地的 modules ,对应到类里的getName()
返回值。
getConstants()
方法负责把类中的常量映射到 JS 中去。
show(String message,int duration)
方法正是我们要提供给 JS 的方法,方法的注释代表这个方法提供给 JS 调用。
三,自定义 Logger
这里我们来自定义一个 LoggerModule 来练练手。这里我先把代码贴出来了。
public class LoggerModule extends ReactContextBaseJavaModule {
private static final String MODULE_NAME = "Logger";
private static final String TAG_KEY = "TAG";
private static final String TAG_VALUE = "LoggerModule";
public LoggerModule(ReactApplicationContext reactContext) {
super(reactContext);
}
@Nullable
@Override
public Map<String,Object> getConstants() {
final Map<String,Object> constants = MapBuilder.newHashMap();
constants.put(TAG_KEY,TAG_VALUE);
return constants;
}
@Override
public String getName() {
return MODULE_NAME;
}
@ReactMethod
public void i(String tag,String msg) {
Log.i(tag,msg);
}
@ReactMethod
public void d(String tag,String msg) {
Log.d(tag,msg);
}
@ReactMethod
public void w(String tag,String msg) {
Log.w(tag,msg);
}
@ReactMethod
public void e(String tag,String msg) {
Log.e(tag,msg);
}
}
这里我把常量TAG
返回给 JS 调用,Module 命名为Logger
,并且把 info,debug,warn,error 等 Log 方法加上@ReactMethod
注释,提供给 JS调用。
这里还没有结束,我们还需要实现一个类,去注册我们自己写的 LoggerModule
。具体代码如下:
public class AppReactPackage implements ReactPackage {
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new LoggerModule(reactContext));
return modules;
}
@Override
public List<Class<? extends JavaScriptModule>> createJSModules() {
return Collections.emptyList();
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}
然后,把这个 AppReactPackage 注册到 Activity。如下:
public class MainActivity extends ReactActivity {
/** * Returns the name of the main component registered from JavaScript. * This is used to schedule rendering of the component. */
@Override
protected String getMainComponentName() {
return "AwesomeProject";
}
/** * Returns whether dev mode should be enabled. * This enables e.g. the dev menu. */
@Override
protected boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
/** * A list of packages used by the app. If the app uses additional views * or modules besides the default ones,add more packages here. */
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),new AppReactPackage()
);
}
}
java 代码到这里就结束了。
下面,我们在index.android.js
的同级目录创建一个 js 文件log.js
。里面内容:
'use strict';
var RCTLogger = require('NativeModules').Logger;//加载本地 modules,Module#getName()
var LogAndroid = {
//添加定义的常量 Module#getConstants()
TAG: RCTLogger.TAG,//添加的方法 Module#d()
d: function(tag: string,msg: string):void{
RCTLogger.d(tag,msg);
},i: function(tag: string,msg: string):void{
RCTLogger.i(tag,w: function(tag: string,msg: string):void{
RCTLogger.w(tag,e: function(tag: string,msg: string):void{
RCTLogger.e(tag,msg);
}
}
module.exports = LogAndroid;//module 导出
这里不用多说了,无非就是创建一个 LogAndroid 对象获取 LoggerModule
java 类中的常量,方法等,并且导出。
下面我贴出完整的index.android.js
,里面显示如何引用:
/** * Sample React Native App * https://github.com/facebook/react-native */
'use strict';
import React,} from 'react-native';
var LogAndroid = require('./log');
LogAndroid.i(LogAndroid.TAG,"Awesome");
LogAndroid.d(LogAndroid.TAG,"Awesome");
LogAndroid.w(LogAndroid.TAG,"Awesome");
LogAndroid.e(LogAndroid.TAG,"Awesome");
ToastAndroid.show('Awesome',ToastAndroid.SHORT);
class AwesomeProject extends Component {
render() {
return (
<View style={styles.container}> <Text style={styles.welcome}> Welcome to React Native! </Text> <Text style={styles.instructions}> To get started,() => AwesomeProject);
重新编译并运行你的 app,看看 logcat 打印出了日志吗?