2017-3-28(React-Native与Android原生代码交互)
本文参考的文章链接如下:
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; }}
讲解一下部分核心代码:
这个类其实就是实现原生代码的调用。
"ToastForAndroid"就是JS调用的那个对象变量。
Paste_Image.png这里也定义了两个常量,放在这个集合中可以供JS调用。
Paste_Image.png该就是供JS调用的方法,这里在java代码需要加注解@ReactMethod
不然在JS那边会调用不了。
最后一个其实也是给JS调用的方法,不过这个方法提供了回调,即
Paste_Image.pngcallback.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();
最后一个java类Application,这个写过Android的应该对这个类并不陌生,其实就是这个Application的生命周期贯穿整个app程序。程序初始化会调用该类的onCreate方法。
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方法
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';
Paste_Image.png loginInOnPress (){ // ToastForAndroid.show(ToastForAndroid.LONG); ToastForAndroid.testAndroidCallbackMethod("hello",(obj)=>{ console.log(obj); }); }
上面是js代码,一个是没有回调的Toast方法,另外一个是有回调的Toast方法。
"hello"是传参给java那边,箭头函数:(obj)=>{console.log(obj)};是回调方法,即刚刚
java那边的‘abc’其实就是js这边的obj对象
基本上ReactNative的JS与Android的原生就这样交互的。其实上边一篇文章中是有三种交互方式的,我这里只说了一种,当时我自己也试了另外的一种,剩下最后一种没有尝试,有空的童鞋可以试试。
最后由于本人第一次写分享文章有什么遗漏或不好望见谅,日后会把demo的源码上传的github上供各位分享。
更多相关文章
- 【Android 初学】5、控件--ImageView的使用方法
- [置顶] 我的Android进阶之旅------>Ubuntu下不能识别Android设备
- Android-Jni线程(三)— JNI全局回调java方法
- Android代码设置EditText只输入数字、字母
- android手机开机动画相关代码解析
- Android 代码混淆及第三方jar包不被混淆
- android 在代码中获取SHA1值
- Android和蓝牙GPS结合的方法