在Android原生中嵌入React Native,进而React Native调用原生

来源:互联网 发布:淘宝热卖排行 编辑:程序博客网 时间:2024/06/05 19:22

首先在Android中嵌入React Native:

每一个Android Studio project下包含多个module,所以,从命令行进入到module根目录,运行:

$ npm init$ npm install --save react-native$ curl -o .flowconfig https://raw.githubusercontent.com/facebook/react-native/master/.flowconfig


上述命令会创建一些react-native依赖的一些模块,在package.json文件的scripts属性中添加:

"start": "node node_modules/react-native/local-cli/cli.js start"

注:如果scripts中存在其他键值对,则以逗号为分隔符。

在module的根目录创建index.android.js文件,并将一下内容下入index.android.js文件:

'use strict';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('HelloWorld', () => HelloWorld);

在Android Studio中,在moudle的build.gradle文件中添加一下内容:

allprojects {    repositories {        ...        maven {            // All of React Native (JS, Android binaries) is installed from npm            url "$rootDir/node_modules/react-native/android"        }    }    ...}
在AndroidManifest.xml文件中添加网络访问权限(仅在开发或调试中需要该权限):

<uses-permission android:name="android.permission.INTERNET"/>

添加原生代码,以此将react native嵌入项目中。创建MyReactActivity类:

package com.example.third;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.view.KeyEvent;import com.example.third.log.AppReactPackage;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;/** * Created by Mini-zy on 16/7/18. */public class MyReactActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler {    private ReactRootView mReactRootView;    private ReactInstanceManager mReactInstanceManager;    @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, "HelloWorld", null);        setContentView(mReactRootView);    }    @Override    public void invokeDefaultOnBackPressed() {        super.onBackPressed();    }    @Override    protected void onPause() {        super.onPause();        if (mReactInstanceManager != null) {            mReactInstanceManager.onHostPause();        }    }    @Override    protected void onResume() {        super.onResume();        if (mReactInstanceManager != null) {            mReactInstanceManager.onHostResume(this, this);        }    }    @Override    protected void onDestroy() {        super.onDestroy();        if (mReactInstanceManager != null) {            mReactInstanceManager.onHostDestroy();        }    }    @Override    public void onBackPressed() {        if (mReactInstanceManager != null) {            mReactInstanceManager.onBackPressed();        } else {            super.onBackPressed();        }    }    @Override    public boolean onKeyUp(int keyCode, KeyEvent event) {        if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {            mReactInstanceManager.showDevOptionsDialog();            return true;        }        return super.onKeyUp(keyCode, event);    }}

代码的详细解释查阅官方。

在命令行,进入module根目录,运行:

$ npm start

不出意外,应该能成功看到Hello World界面。


下面进入React Native调用Android原生部分。

首先,我们来创建一个用于React Native调用的class,名为JsAndroidModule:

package com.example.third.js;import com.facebook.react.bridge.ReactApplicationContext;import com.facebook.react.bridge.ReactContextBaseJavaModule;/** * Created by Mini-zy on 16/7/18. */public class JsAndroidModule extends ReactContextBaseJavaModule{    private static final String MODULE_NAME="JsAndroid";    public JsAndroidModule(ReactApplicationContext reactContext) {        super(reactContext);    }    @Override    public String getName() {        return MODULE_NAME;    }}
JsAndroidModule中MODULE_NAME指定了React Native调用原生的名称。

然后,在JsAndroidModule中添加给React Native调用的方法:

    @ReactMethod    public void jsActivity(){        Intent intent = new Intent(MyApp.getContext(),JsActivity.class);        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);        MyApp.getContext().startActivity(intent);    }

React Native调用的方法需要使用@ReactMethod注解,jsActivity()方法启动一个新的Activity。MyApp继承了Application,为全局提供Context。

创建JsReactPackage,用于注册JsAndroidModule:

package com.example.third.js;import com.example.third.log.LogModule;import com.facebook.react.ReactPackage;import com.facebook.react.bridge.JavaScriptModule;import com.facebook.react.bridge.NativeModule;import com.facebook.react.bridge.ReactApplicationContext;import com.facebook.react.uimanager.ViewManager;import java.util.ArrayList;import java.util.Collections;import java.util.List;/** * Created by Mini-zy on 16/7/18. */public class JsReactPackage implements ReactPackage {    @Override    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {        List<NativeModule> modules = new ArrayList<>();        modules.add(new JsAndroidModule(reactContext));        return modules;    }    @Override    public List<Class<? extends JavaScriptModule>> createJSModules() {        return Collections.emptyList();    }    @Override    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {        return Collections.emptyList();    }}

在上文中MyReactActivity类中的onCreate方法中初始化JsReactPackage:

    @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())                .addPackage(new AppReactPackage())                .addPackage(new JsReactPackage())                .setUseDeveloperSupport(BuildConfig.DEBUG)                .setInitialLifecycleState(LifecycleState.RESUMED)                .build();        mReactRootView.startReactApplication(mReactInstanceManager, "HelloWorld", null);        setContentView(mReactRootView);    }
注:这里和官方给出不同。官方说在MainActivity中添加getPackages()函数,但是出现了异常。同时,考虑到官方的场景与本文不同,所以应该在MyReactActivity类中初始化。

官方说可以使用一个单例来管理ReactInstanceManager。


在与index.android.js相同的目录下创建JsAndroid.js文件:

'use strict';import { NativeModules } from 'react-native';module.exports = NativeModules.JsAndroid;

代码中的JsAndroid就是JsAndroidModule.class中指定的模块名。

在index.android.js文件中饮用JsAndroid模块,并添加按钮,调用jsActivity方法:

'use strict';import React from 'react';import {  AppRegistry,  StyleSheet,  Text,  View,  TouchableOpacity} from 'react-native';import Log from './Log';import JsAndroid from './JsAndroid';class HelloWorld extends React.Component {  constructor(props){    super(props);    //console.log(NativeActivity);    Log.d('Succ','Success!!!');    Log.i('Succ','Success!!!');  }  _newNativeActivity(){    JsAndroid.jsActivity();  }  render() {    return (      <View style={styles.container}>        <Text style={styles.hello}>Hello, World</Text>        <TouchableOpacity onPress={this._newNativeActivity}>          <Text>New Native Activity</Text>        </TouchableOpacity>      </View>    )  }}var styles = StyleSheet.create({  container: {    flex: 1,    justifyContent: 'center',  },  hello: {    fontSize: 20,    textAlign: 'center',    margin: 10,  },});AppRegistry.registerComponent('HelloWorld', () => HelloWorld);

最后,运行,注意npm start。

0 0
原创粉丝点击