本文参考的文章链接如下:
React-Native 与原生的3种交互通信(Android)
React Native 调用原生Android模块

原生与React-NativeJSX交互的涉及到的java类:

  • ReactContextBaseJavaModule : 用于自定义实现原生代码调用
  • ReactPackage :用于注册java代码在JSX代码使用
  • ReactApplication : 实现ReactNativeHost单例方式存储继承ReactPackage

继承ReactContextBaseJavaModule

package com.reactnativeproject;import android.widget.Toast;import com.facebook.react.bridge.Callback;import com.facebook.react.bridge.ReactApplicationContext;import com.facebook.react.bridge.ReactContextBaseJavaModule;import com.facebook.react.bridge.ReactMethod;import java.util.HashMap;import java.util.Map;import javax.annotation.Nullable;/** * Created by Gww on 2017/3/27. * 原生的代码,之后与JS交互 */public class ToastExample extends ReactContextBaseJavaModule{    private static final String LONG_TIME = "LONG";    private static final String SHORT_TIME = "SHORT";    public ToastExample(ReactApplicationContext reactContext) {        super(reactContext);    }    /**     * return string 这个名字在JavaScript端标记这个模块     * 这样就可以在JavaScript中通过React.NativeModules.ToastForAndroid访问到这个模块     * */    @Override    public String getName() {        return "ToastForAndroid";    }    /**     * return 需要导出给JavaScript使用的常量。它并不一定需要实现,但在定义一些可以被JavaScript同步访问到的预定义的值时非常有用。     * */    @Override    public Map getConstants() {        //让js那边能够使用这些常量        Map constants = new HashMap<>();        constants.put(LONG_TIME,Toast.LENGTH_LONG);        constants.put(SHORT_TIME,Toast.LENGTH_SHORT);        return constants;//        return super.getConstants();    }    /**     * 该方法就是给js使用     * Java方法需要使用注解@ReactMethod。     * 方法的返回类型必须为void。     * React Native的跨语言访问是异步进行的,所以想要给JavaScript返回一个值的唯一办法是使用回调函数或者发送事件     * */    @ReactMethod    public void show(int duration){        Toast.makeText(getReactApplicationContext(),"message",duration).show();    }    /**     * 测试安卓的回调方法     * */    @ReactMethod    public void testAndroidCallbackMethod(String msg, Callback callback){        Toast.makeText(getReactApplicationContext(),msg,Toast.LENGTH_LONG).show();        callback.invoke("abc");    }    @Override    public boolean canOverrideExistingModule() {        //这里需要返回true        return true;    }}

讲解一下部分核心代码:
这个类其实就是实现原生代码的调用。

2017-3-28(React-Native与Android原生代码交互)_第1张图片 Paste_Image.png

"ToastForAndroid"就是JS调用的那个对象变量。

2017-3-28(React-Native与Android原生代码交互)_第2张图片 Paste_Image.png

这里也定义了两个常量,放在这个集合中可以供JS调用。

2017-3-28(React-Native与Android原生代码交互)_第3张图片 Paste_Image.png

该就是供JS调用的方法,这里在java代码需要加注解@ReactMethod
不然在JS那边会调用不了。

最后一个其实也是给JS调用的方法,不过这个方法提供了回调,即

2017-3-28(React-Native与Android原生代码交互)_第4张图片 Paste_Image.png

callback.invoke('abc');这里可以把信息回调给JS那边。

ReactPackage

现在说另一个类ReactPackage,其实该类的基本作用就是把继承ReactContextBaseJavaModule类的方法注册到JS里。上代码吧:

package com.reactnativeproject;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.Collection;import java.util.Collections;import java.util.List;/** * Created by Gww on 2017/3/27. * 在reactnative注册用于js调用 */public class ExampleReactNativePackage implements ReactPackage{    @Override    public List createNativeModules(ReactApplicationContext reactContext) {        List modules = new ArrayList<>();        modules.add(new ToastExample(reactContext));        return modules;    }    @Override    public List> createJSModules() {        return Collections.emptyList();    }    @Override    public List createViewManagers(ReactApplicationContext reactContext) {        return Collections.emptyList();    }}

其中就把ToastExample对象添加到modules这个list上。
还有两个方法返回Collections.emptyList();

2017-3-28(React-Native与Android原生代码交互)_第5张图片 Paste_Image.png

最后一个java类Application,这个写过Android的应该对这个类并不陌生,其实就是这个Application的生命周期贯穿整个app程序。程序初始化会调用该类的onCreate方法。

2017-3-28(React-Native与Android原生代码交互)_第6张图片 Paste_Image.png

在ReactNative中,我们需要Application这个类实现ReactApplication这个接口,其实我们初始化一个ReactNative项目的java代码已经有这个Application类也已经实现了该接口。在这里其实我们只需要在Application这个对象构建时new一个ReactnativeHost对象,在getPackages方法重写一下,返回一个数组,该数组新增一个之前用于注册java方法的ExampleReactNativePackage对象。

这里说一下如果是原生跟ReactNative混搭的话,自己项目拥有一个Application类的话其实就按照接口的操作即可。上代码吧:

package com.reactnativeproject;import android.app.Application;import com.facebook.react.ReactApplication;import com.facebook.react.ReactNativeHost;import com.facebook.react.ReactPackage;import com.facebook.react.shell.MainReactPackage;import com.facebook.soloader.SoLoader;import java.util.Arrays;import java.util.List;public class MainApplication extends Application implements ReactApplication {    private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {        @Override        public boolean getUseDeveloperSupport() {            return BuildConfig.DEBUG;//这是true,返回false是会报错找不到AppRegistry        }        @Override        protected List getPackages() {            return Arrays.asList(                    new MainReactPackage(),                    new ExampleReactNativePackage()/*自定义的一个package*/            );        }    };    @Override    public ReactNativeHost getReactNativeHost() {        return mReactNativeHost;    }    @Override    public void onCreate() {        super.onCreate();        SoLoader.init(this, /* native exopackage */ false);    }}

基本上java这边就这么多东西了。

然后看看js那边怎么调用和导出一个对象:

JS导出
import {NativeModules} from 'react-native';export default NativeModules.ToastForAndroid;

其中ToastForAndroid就是对应java那边所说的getName方法

2017-3-28(React-Native与Android原生代码交互)_第7张图片 Paste_Image.png

这个java和js一一对应的,不然JS会找不到此对象。

JS调用

调用前需要导入刚才的ToastForAndroid对象供这边的JS使用:

import React,{Component} from 'react';import {    StyleSheet,Text,Image,View, TextInput, TouchableHighlight, Navigator, BackAndroid,Platform} from 'react-native';import ToastUtil from '../utils/ToastUtil';//export default的class就可以不用{}括组件,直接用ToastUtilimport HelloWorld from '../00_helloworld_demo/HelloWorld';import ToastForAndroid from '../utils/ToastForAndroid';
2017-3-28(React-Native与Android原生代码交互)_第8张图片 Paste_Image.png
loginInOnPress (){        // ToastForAndroid.show(ToastForAndroid.LONG);        ToastForAndroid.testAndroidCallbackMethod("hello",(obj)=>{            console.log(obj);        });    }

上面是js代码,一个是没有回调的Toast方法,另外一个是有回调的Toast方法。
"hello"是传参给java那边,箭头函数:(obj)=>{console.log(obj)};是回调方法,即刚刚

2017-3-28(React-Native与Android原生代码交互)_第9张图片 Paste_Image.png

java那边的‘abc’其实就是js这边的obj对象

基本上ReactNative的JS与Android的原生就这样交互的。其实上边一篇文章中是有三种交互方式的,我这里只说了一种,当时我自己也试了另外的一种,剩下最后一种没有尝试,有空的童鞋可以试试。

最后由于本人第一次写分享文章有什么遗漏或不好望见谅,日后会把demo的源码上传的github上供各位分享。

更多相关文章

  1. 【Android 初学】5、控件--ImageView的使用方法
  2. [置顶] 我的Android进阶之旅------>Ubuntu下不能识别Android设备
  3. Android-Jni线程(三)— JNI全局回调java方法
  4. Android代码设置EditText只输入数字、字母
  5. android手机开机动画相关代码解析
  6. Android 代码混淆及第三方jar包不被混淆
  7. android 在代码中获取SHA1值
  8. Android和蓝牙GPS结合的方法

随机推荐

  1. 游戏音频-详解MediaPlayer,SoundPool利弊
  2. shareSdk错误码对照表
  3. (Android(安卓)) wrapper was not proper
  4. Android自屏幕底部滑出更多面板的实现
  5. Bluetooth---如何使用Android蓝牙开发
  6. aapt.AaptException Failed to crunch fi
  7. Android(安卓)TextView部分文字实现点击
  8. Android(安卓)MediaPlayer 播放本地与远
  9. android 文件的认识
  10. 极光推送和百度lbs android sdk一起使用