React Native Android入门实战及深入源码分析系列(1)——Hello world

转载需注明出处:http://blog.csdn.net/minimicall?viewmode=contents

从今天起,我要分析React Native for Android的源码。

本系列主要是从使用和源码分析的角度来一步步的剖析React Native Android。当然,因为我对IOS不了解,所以,我只能分析安卓了。

首先来一个Hello world。

对于Rn 安卓的开发环境,本着不重复造轮子的思想,我就不再这里介绍了。

1、 创建一个工程

首先,我们需要创建一个Rn工程,通过如下命令:

react-native init AweSomeProject

然后我们进入到该工程目录下。选择android目录:

确认里面有build.gradle文件。我们可以通过react-native run-android 来运行安卓程序。但,为了后续开发,我们选择使用AndroidStudio来打开。

在import project的时候,选择该android目录。然后就导入了工程。等待漫长的gradle更新过程吧,这个时候貌似在天朝需要vpn吧。

等待完了之后,点击run,运行程序,我们假设你已经有创建一个虚拟手机了,在电脑上。因为真机的话,我们后面再讲。因为它有点复杂。

这个时候你可以看到其实手机上已经有了效果。

2、MainActivity分析

这个时候,项目已经默认创建了一个MainActivity。我们来分析一下它的源码:

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 ToastReactPackage()
      );
    }
}

英文注释已经解释的非常明白了。其实,我们定制模块最重要的是在getPackages()方法加上自己需要注册的模块。例如,我这里就注册了ToastReactPackage。这个等会说。

3、 index.android.js 文件

我们回过头来说js文件。打开这个文件,已经有了默认的。但我并不满足于它,我做一个简单的相册吧。

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 */
'use strict';
import React, {
  AppRegistry,
  Component,
  StyleSheet,
  Text,
  View,
  Image
} from 'react-native';

import KankanToast from './androidview/ToastAndroid';

var imgs = [
  'http://www.ituring.com.cn/bookcover/1442.796.jpg',
  'http://www.ituring.com.cn/bookcover/1668.553.jpg',
  'http://www.ituring.com.cn/bookcover/1521.260.jpg'
];

var MyImage = React.createClass({
  getInitialState:function(){
    return {imgs:imgs,count:0};
  },
  goNext:function(){
    var count = this.state.count;
    count ++ ;
    if(count < imgs.length){
      this.setState({
        count:count
      });
    }
  },
  goPreview:function(){
    var count = this.state.count;
    count --;
    if(count >= 0){
      this.setState({count:count});
    }
  },
  render:function(){
    return (
    <View style={styles.flex}>
      <View style={styles.image}>
        <Image style = {styles.img}
            source = {{uri:this.state.imgs[this.state.count]}}
            resizeMode="contain"
        />
      </View>
      <View style={styles.btns}>
        <TouchableOpacity onPress={this.goPreview}>
          <View style={styles.btn}>
            <Text>Prev</Text>
          </View>
        </TouchableOpacity>
          <TouchableOpacity onPress={this.goNext}>
          <View style={styles.btn}>
            <Text>Next</Text>
          </View>
        </TouchableOpacity>
      </View>
    </View>
      );

  }
});

KankanToast.show('这是一个Toast',KankanToast.SHORT);

class AwesomeProject extends Component {
  render() {
    return (
      <View style={styles.container}>
        <MyImage></MyImage>
      </View>
    );
  }
}

const 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,
  },
  image:{
    borderWidth:1,
    width:300,
    height:200,
    borderRadius:5,
    borderColor:'#ccc',
    justifyContent:'center',
    alignItems:'center'
  },
  img:{
    height:150,
    width:200
  },
  btns:{
    flexDirection:'row',
    justifyContent:'center',
    marginTop:20
  },
  btn:{
    width:60,
    height:30,
    borderColor:'#0089FF',
    borderWidth:1,
    justifyContent:'center',
    alignItems:'center',
    borderRadius:3,
    marginRight:20
  }

});

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

迫不及待的我们先来看一看效果:

弹了个Toast,你看,是不是和安卓原生态的一个墨阳。哎呀,模样。其实,墨阳这个名字真好听。

然后,就出来了我们期待的相册。是不是丑了点,将就着看吧,你行你上,不行别逼逼。

我们来分析一下这个源码的意思。

这段代码就是js的全部代码。我们来说明一下代码的含义。

1)导入:

import React, {
  AppRegistry,
  Component,
  StyleSheet,
  Text,
  View,
  Image
} from 'react-native';
上面是从react-native库里面导入对应的模块

import KankanToast from './androidview/ToastAndroid';

这个有意思了,这个是从当前目录下的androidview子目录下导入ToastAndroid模块。其实就是./androidview/ToastAndroid.js文件。它的内容我们后面再说

2、定义个数组

var imgs = [
  'http://www.ituring.com.cn/bookcover/1442.796.jpg',
  'http://www.ituring.com.cn/bookcover/1668.553.jpg',
  'http://www.ituring.com.cn/bookcover/1521.260.jpg'
];

这个数组用来存储图片路径。

3、定义一个UI控件

var MyImage = React.createClass({...});

这个就是我们威名远扬的相册控件。

4、弹出一个Toast

KankanToast.show('这是一个Toast',KankanToast.SHORT);

看清楚,我用的是KankanToast,这个是我自己定义的一个组件。至于为什么要叫KankanToast,主要是曾老师是迅雷看看的一名资深开发屌丝。

当然,我们改名了,改成响巢看看,响巢看看,响巢看看。重要的事情说三遍,要是没记住,我就送你一张爱奇艺的会员卡了,对是爱奇艺的。

5、程序的入口组件

class AwesomeProject extends Component

这个里面有个render函数,注意它的根节点只能有一个<View>

6、定义css样式

const styles = StyleSheet.create

这个就不用多说了。

7、注册程序入口组件

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

到这里我们把js的代码说完了。回过头,我们得说说我们的KankanToast是怎么个回事。

当然,你最好把它注释掉。因为,我下篇再讲,今天太晚了,要睡觉了。不要问为什么,我工资低,比较任性。

晚安。下一篇,自定义控件。

时间: 2024-06-19 16:33:53

React Native Android入门实战及深入源码分析系列(1)——Hello world的相关文章

React Native Android入门实战及深入源码分析系列(2)——React Native源码编译

本文为老曾原创,转载需注明出处:http://blog.csdn.net/minimicall?viewmode=contents 在上一节中,我们通过一个相册的制作来学习了React Native编写.这一节我们需要开始学习React Native的源码. 学习源码,从编译源码开始. 首先,我们需要把代码从github中克隆下来. https://github.com/facebook/react-native.git 然后,我们可以切换到它的稳定分支,2016-03-30是我的操作时间,这个

Jquery1.9.1源码分析系列(十五)动画处理之外篇_jquery

a.动画兼容Tween.propHooks Tween.propHooks提供特殊情况下设置.获取css特征值的方法,结构如下 Tween.propHooks = { _default: { get: function(){...}, set: function(){...} }, scrollTop: { set: function(){...} } scrollLeft: { set: function(){...} } } Tween.propHooks.scrollTop 和Tween.

dubbo源码分析系列(4)dubbo通信设计

1 系列目录 dubbo源码分析系列(1)扩展机制的实现 dubbo源码分析系列(2)服务的发布 dubbo源码分析系列(3)服务的引用 dubbo源码分析系列(4)dubbo通信设计 2 NIO通信层的抽象 目前dubbo已经集成的有netty.mina.grizzly.先来通过案例简单了解下netty.mina编程(grizzly没有了解过) 2.1 netty和mina的简单案例 netty原本是jboss开发的,后来单独出来了,所以会有两种版本就是org.jboss.netty和io.n

dubbo源码分析系列(1)扩展机制的实现

1 系列目录 dubbo源码分析系列(1)扩展机制的实现 dubbo源码分析系列(2)服务的发布 dubbo源码分析系列(3)服务的引用 dubbo源码分析系列(4)dubbo通信设计 2 SPI扩展机制 站在一个框架作者的角度来说,定义一个接口,自己默认给出几个接口的实现类,同时允许框架的使用者也能够自定义接口的实现.现在一个简单的问题就是:如何优雅的根据一个接口来获取该接口的所有实现类呢? 这就需要引出java的SPI机制了 2.1 SPI介绍与demo 这些内容就不再多说了,网上搜一下,一

dubbo源码分析系列(3)服务的引用

1 系列目录 dubbo源码分析系列(1)扩展机制的实现 dubbo源码分析系列(2)服务的发布 dubbo源码分析系列(3)服务的引用 dubbo源码分析系列(4)dubbo通信设计 2 服务引用案例介绍 先看一个简单的客户端引用服务的例子,dubbo配置如下: <dubbo:application name="consumer-of-helloService" /> <dubbo:registry protocol="zookeeper" ad

dubbo源码分析系列(2)服务的发布

1 系列目录 dubbo源码分析系列(1)扩展机制的实现 dubbo源码分析系列(2)服务的发布 dubbo源码分析系列(3)服务的引用 dubbo源码分析系列(4)dubbo通信设计 2 dubbo与spring接入 dubbo的官方文档也说明了,dubbo可以不依赖任何Spring.这一块日后再详细说明,目前先介绍dubbo与Spring的集成.与spring的集成是基于Spring的Schema扩展进行加载 2.1 Spring对外留出的扩展 用过Spring就知道可以在xml文件中进行如

jQuery-1.9.1源码分析系列(十)事件系统之事件包装_jquery

在上篇文章给大家介绍了jQuery-1.9.1源码分析系列(十)事件系统之事件体系结构,本篇继续给大家介绍jquery1.9.1源码分析系列相关知识,具体内容请看下文吧. 首先需要明白,浏览器的原生事件是只读的,限制了jQuery对他的操作.举个简单的例子就能明白为什么jQuery非要构造一个新的事件对象. 在委托处理中,a节点委托b节点在a被click的时候执行fn函数.当事件冒泡到b节点,执行fn的时候上下文环境需要保证正确,是a节点执行了fn而非b节点.如何保证执行fn的上下文环境是a节点

jQuery-1.9.1源码分析系列(十一)DOM操作续之克隆节点_jquery

什么情况下使用到克隆节点? 我们知道在对DOM操作过程中如果直接使用节点会出现节点随操作而变动的情况.比如对节点使用.after/.before/.append等方法后,节点被添加到新的地方,原来的位置上的节点被移除了.有的时候需要保留原来位置上的节点,仅仅是需要一个副本添加到对应位置,这个时候克隆就有了使用场景. jQuery.fn.clone克隆当前匹配元素集合的一个副本,并以jQuery对象的形式返回. 你还可以指定是否复制这些匹配元素(甚至它们的子元素)的附加数据( data()函数 )

Jquery1.9.1源码分析系列(六)延时对象应用之jQuery.ready_jquery

还记不记得jQuery初始化函数jQuery.fn.init中有这样是一个分支 //document ready简便写法$(function(){-}) } else if ( jQuery.isFunction( selector ) ) { return rootjQuery.ready( selector ); } 所以$(fn)===$(document).ready(fn). 来看一下jQuery.fn.ready的源码 ready: function( fn ) { // Add t