zoukankan      html  css  js  c++  java
  • 从零学React Native之05混合开发

    本篇文章,我们主要讨论如何实现Android平台的混合开发.

    RN给Android端发送消息

    首先打开Android Studio, Open工程, 在React Native项目目录下选择android子目录下的build.gradle文件打开。

    这里写图片描述

    React Native已经默认帮我们创建好了两个类MainApplication和MainActivity

    public class MainApplication extends Application implements ReactApplication {
    
        private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
            //之前版本该代码是在MainActivity中
            @Override
            protected boolean getUseDeveloperSupport() {
                return BuildConfig.DEBUG;
            }
    
            //开发者编写的React包管理器的实例需要在getPackages函数中被创建
            @Override
            protected List<ReactPackage> getPackages() {
                return Arrays.<ReactPackage>asList(
                        new MainReactPackage()
                );
            }
        };
    
        @Override
        public ReactNativeHost getReactNativeHost() {
            return mReactNativeHost;
        }
    }
    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";
        }
    }

    除了上面的代码,我们需要打通RN和原生代码, Android侧的接口类需要继承ReactContextBaseJavaModule

    public class ExampleRNInterface extends ReactContextBaseJavaModule{
        public ExampleRNInterface(ReactApplicationContext reactContext) {
            super(reactContext);
        }
        // 这个函数的用途是返回原生代码模块的名称
        @Override
        public String getName() {
            return "ExampleRNInterface";
        }
        @ReactMethod   //必须有当前注解, 否则不能被RN调用, 函数也不能有返回值
        public void handleMessage(String message){// 这是原生代码处理消息
            //输出日志
            Log.i("ExampleRNInterface","在RN接受到了消息:"+message);
    
        }
    }

    getName()函数必须实现,这个函数的用途是返回原生代码模块的名称,在RN侧使用这个名称来调用原生代码模块提供的其他函数。
    handleMessage 是自定义的函数 需要使用@ReactMethod标识,否则不能在RN中调用, 并且函数不能有返回值,因为调用的原生代码是异步执行的。

    做完上面的操作,最后还需要注册开发者编写的原生代码模块,首先需要实现一个React包管理类,继承ReactPackage,并且实现createNativeModules方法,实际的注册过程将在createNativeModules函数被调用时发生。
    如下,创建了ExampleReactPackage

    代码:
    /**
     * 实现React包管理类
     * Created by yull on 08/05.
     */
    public class ExampleReactPackage implements ReactPackage {
        //实际注册过程将在createNativeModules函数被调用时发生
        @Override
        public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
            List<NativeModule> modules=new ArrayList<>();
            modules.add(new ExampleRNInterface(reactContext));
            return modules;
        }
    
        @Override
        public List<Class<? extends JavaScriptModule>> createJSModules() {
            return Collections.emptyList();
        }
    
        @Override
        public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
            return  Collections.emptyList();
        }
    }

    咱们编写的React包管理器的实例需要在MainApplication.java中的ReactNativeHost里面的getPackages()中被创建,如下:

        private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
            //之前版本是在MainActivity中
            @Override
            protected boolean getUseDeveloperSupport() {
                return BuildConfig.DEBUG;
            }
    
            //开发者编写的React包管理器的实例需要在getPackages函数中被创建
            @Override
            protected List<ReactPackage> getPackages() {
                return Arrays.asList(
                        new MainReactPackage(),
                        new ExampleReactPackage()//创建自己编写的包管理器
                );
            }
        };

    在React Native侧, 开发者可以调用Android侧的代码了:

    import {
        //...
        NativeModules
    } from 'react-native';
    
    let ExampleRNInterface=NativeModules.ExampleRNInterface;
    
    class AwesomeProject extends Component {
        render() {
            return (
                <View style={styles.container}>
                    <Text style={styles.welcome}
                          onPress={this.buttonPressed}>
                        Welcome to React Native!
                    </Text>
                </View>
            );
        }
        buttonPressed(){
            NativeModules.ExampleRNInterface.handleMessage('testMessage');
        }
    }
    
    const styles = StyleSheet.create({
       //...
    });
    
    AppRegistry.registerComponent('AwesomeProject', () => AwesomeProject);

    这里写图片描述
    点击屏幕上的文字就会在Android Studio中看到日志了

    PS: 修改完了Andorid端代码,貌似需要编译一回,才能生效, 我直接运行了下Android代码,然后reloadJS就生效了

    这里写图片描述

    RN与Android原生端界面的切换

    直接在Android端创建新的Activity, 然后修改上面的ExampleRNInterface

    public class ExampleRNInterface extends ReactContextBaseJavaModule{
        ReactApplicationContext reactContext;
        public ExampleRNInterface(ReactApplicationContext reactContext) {
            super(reactContext);
            this.reactContext=reactContext;//保存上下文
        }
    
        // 这个函数的用途是返回原生代码模块的名称
        @Override
        public String getName() {
            return "ExampleRNInterface";
        }
        @ReactMethod   //必须有当前注解, 否则不能被RN调用, 函数也不能有返回值
        public void handleMessage(String message){// 这是原生代码处理消息
            //输出日志
            Log.i("ExampleRNInterface","在RN接受到了消息:"+message);
            Intent intent=new Intent(reactContext, Main2Activity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            reactContext.startActivity(intent);
        }
    }

    运行结果:

    这里写图片描述

    Android发送消息给RN

    首先Android侧修改ExampleRNInterface

    public class ExampleRNInterface extends ReactContextBaseJavaModule{
        ...
        @ReactMethod   //必须有当前注解, 否则不能被RN调用, 函数也不能有返回值
        public void handleMessage(String message){// 这是原生代码处理消息
            sendMessage("I am Android!");
        }
        //发送消息
        public void sendMessage(String message){
            reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                    .emit("Android2RN",message);
        }
    }

    React Native侧

    class AwesomeProject extends Component {
        componentWillMount() {
            console.log('componentWillMount');
            //监听消息和Android端保持一致
            DeviceEventEmitter.addListener('Android2RN',this.handleMessage);
        }
        handleMessage(message){
            console.log(message);
        }
        ...
    }

    运行结果 , 当点击屏幕文字的时候 控制台就会打印Android侧返回的日志
    这里写图片描述

    监听Android onActivityResult事件

    开发者也可以选择直接在Android与React Native的接口类中监听启动Activity的结果。如ExampleRNInterface 实现ActivityEventListener

    常量

    混合开发中,可以实现getContants的成员函数, 把Android原生的常量暴漏给RN侧,这种方法对混合开发有一定的用处

        @Override
        public Map<String, Object> getConstants() {
            final Map<String,Object> constants=new HashMap<>();
            constants.put("constantName",contantValue);
            return constants;
        }

    在RN侧, 开发者可以通过nativeModuleName.constantName来访问被导出的常量

    更多精彩请关注微信公众账号likeDev,公众账号名称:爱上Android。
    likeDev.jpg

  • 相关阅读:
    CS224n, lec 10, NMT & Seq2Seq Attn
    CS231n笔记 Lecture 11, Detection and Segmentation
    CS231n笔记 Lecture 10, Recurrent Neural Networks
    CS231n笔记 Lecture 9, CNN Architectures
    CS231n笔记 Lecture 8, Deep Learning Software
    CS231n笔记 Lecture 7, Training Neural Networks, Part 2
    pytorch坑点排雷
    Sorry, Ubuntu 17.10 has experienced an internal error
    VSCode配置python插件
    tmux配置与使用
  • 原文地址:https://www.cnblogs.com/hehe520/p/6329896.html
Copyright © 2011-2022 走看看