React-Native Android 学习笔记——2,自定义 logger

通过上一篇《 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, {
  AppRegistry,
  Component,
  StyleSheet,
  Text,
  View,
} 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,
    textAlign: 'center',
    margin: 10,
    color:'red'
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});

标签的具体规范可以看这里TextView

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

上面这段代码把我们 js 文件中的 class AwesomeProject和我们 Android 项目中 ActivitygetMainComponentName() { 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, {
  AppRegistry,
  Component,
  StyleSheet,
  Text,
  ToastAndroid,
  View,
} 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,
  LONG: RCTToastAndroid.LONG,

  show: function (
    message: string,
    duration: number
  ): void {
    RCTToastAndroid.show(message, duration);
  },

};

这段代码,创建一个对象赋值给ToastAndroid,对象内分别设置了ToastSHORTLONGshow方法。
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,msg);
  },

  w: function(tag: string,msg: string):void{
    RCTLogger.w(tag,msg);
  },

  e: function(tag: string,msg: string):void{
    RCTLogger.e(tag,msg);
  }
}

module.exports = LogAndroid;//module 导出

这里不用多说了,无非就是创建一个 LogAndroid 对象获取 LoggerModulejava 类中的常量,方法等,并且导出。
下面我贴出完整的index.android.js,里面显示如何引用:

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 */
'use strict';
import React, {
  AppRegistry,
  Component,
  StyleSheet,
  Text,
  ToastAndroid,
  View,
} 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, 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);

重新编译并运行你的 app,看看 logcat 打印出了日志吗?

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值