Wang Gang ReactNative development 10 ---- ReactNative with native intermodulation process Detailed

1, Why RN and native intermodulation?
RN will not complete things, such as opening a local camera, native interface. Dealing with hardware, then they die.
2, the first to use Android studio open android directory under ReactNative project;
we look at this project: it has two classes, MainActivity and MainApplication; in app.gradle file, dependencies (dependent), you will find that it has a react-native dependencies.
3, js call the java, is the first call js c, c calling java.
4, js call java process
Here Insert Picture Description
Here Insert Picture Description
to create ToastExampleMoudle

package com.nativeapp;

import android.widget.Toast;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.Nullable;
//
public class ToastExampleMoudle extends ReactContextBaseJavaModule {
    private static final String MESSAGE = "MESSAGE";
    public ToastExampleMoudle(ReactApplicationContext reactContext) {
        super(reactContext);
    }
  
    //通过js去弹出一个原生的吐丝
    @ReactMethod//要想这个方法暴露给js必须增加这个注解
    public void show(int duration){
        Toast.makeText(getReactApplicationContext(), "dongnao:" + duration, Toast.LENGTH_SHORT).show();
    }
  
    @Override
    public String getName() {
        return "ToastForAndroid";
    }

    @Override
    public boolean canOverrideExistingModule() {
        return true;
    }
}

Creating ExampleReactNativePackage class

package com.nativeapp;

import com.facebook.react.ReactPackage;
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;

//注册模块,注册到c
public class ExampleReactNativePackage implements ReactPackage {
//完成注入,需要被js调用java方法
    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
    //NativeModule添加到这个集合里,React Native通过这个方法知道当前有多少个需要给js调用的对象
        List<NativeModule> modules = new ArrayList<>();
        modules.add(new ToastExampleMoudle(reactContext));
        return modules;
    }

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
    //注意这里不能写return null;
        return Collections.emptyList();
    }
}

This is MainActivity

package com.nativeapp;

import com.facebook.react.ReactActivity;

public class MainActivity extends ReactActivity {

    /**
     * Returns the name of the main component registered from JavaScript.
     * This is used to schedule rendering of the component.
     */
     //这里的nativeapp与index.js中的appName名字一样
     //AppRegistry.registerComponent(appName, () => App);
    @Override
    protected String getMainComponentName() {
        return "nativeapp";
    }
}

Modify MainApplication

package com.nativeapp;

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;
//注册java的模块,提前应用到缓存中心
public class MainApplication extends Application implements ReactApplication {
// reactNative主机
  private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
    @Override
    public boolean getUseDeveloperSupport() {
    //是否是开发者
      return BuildConfig.DEBUG;
    }

    @Override
    protected List<ReactPackage> getPackages() {
    //返回的是一个集合
      return Arrays.<ReactPackage>asList(
          new MainReactPackage(),
          //添加我们定义的ReactPackage
              new ExampleReactNativePackage()
      );
    }
    @Override
    protected String getJSMainModuleName() {
    //指向了程序的入口,index就是rn的主界面
      return "index";
    }
  };
  @Override
  public ReactNativeHost getReactNativeHost() {
    return mReactNativeHost;
  }

  @Override
  public void onCreate() {
    super.onCreate();
    SoLoader.init(this, /* native exopackage */ false);
  }
}

Look App.js file

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *
 * @format
 * @flow
 * @lint-ignore-every XPLATJSCOPYRIGHT1
 */

import React, {Component} from 'react';
//这里的ToastAndroid,是ToastExampleMoudle类中方法
//     @Override
//     public String getName() {
//         return "ToastForAndroid";
//     }
//     返回的名字。
import {
    Platform,
    StyleSheet,
    ToastAndroid,
    DeviceEventEmitter,
    Text,
    TouchableOpacity,
    View,
    NativeModules
} from 'react-native';

export default class App extends Component<Props> {
     _onPressButton() {
        /*调用ToastExampleMoudle类这个方法
         * @ReactMethod
         * public void show(int duration){
         *   Toast.makeText(getReactApplicationContext(), "dongnao:" + duration, Toast.LENGTH_SHORT).show();
         *   }
         */
         // NativeModules.ToastForAndroid就表示调用ToastExampleMoudle类。
        NativeModules.ToastForAndroid.show(1000);
    }

    
     

    render() {
        return (
            <View style={styles.container}>
                //this._onPressButton.bind(this),调用_onPressButton(),注意这里是es6写法
                <TouchableOpacity onPress={this._onPressButton.bind(this)}>
                    <Text style={styles.hello}>点击了</Text>
                </TouchableOpacity>
   </View>
        );
    }
}

const styles = StyleSheet.create({
    hello: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
    },
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
    },
    welcome: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
    },
    instructions: {
        textAlign: 'center',
        color: '#333333',
        marginBottom: 5,
    },
});

We run the project, click on the word "hit", will pop up spinning
5,Here Insert Picture Description

ToastExampleMoudle type which add the following code

   //1,具有回调参数的
    //2,callback是ReactNative里面的一个接口。这个接口只有一个方法。
    @ReactMethod
    public void testAndroidCallBack(String msg, Callback callback) {
        Toast.makeText(getReactApplicationContext(),msg,Toast.LENGTH_LONG).show();
        //invoke方法的参数是一个可变参数
        callback.invoke("david");
    }

Modify app.js class

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *
 * @format
 * @flow
 * @lint-ignore-every XPLATJSCOPYRIGHT1
 */

import React, {Component} from 'react';
//这里的ToastAndroid,是ToastExampleMoudle类中方法
//     @Override
//     public String getName() {
//         return "ToastForAndroid";
//     }
//     返回的名字。
import {
    Platform,
    StyleSheet,
    ToastAndroid,
    DeviceEventEmitter,
    Text,
    TouchableOpacity,
    View,
    NativeModules
} from 'react-native';

export default class App extends Component<Props> {
    constructor(props) {
        super(props);
        this.state = {
            text: "river",
            text2: "默认",
        }

    }

 
   

    _onPressButton2() {
        NativeModules.ToastForAndroid.testAndroidCallBack("hello David", (result) => {
            this.setState({
                text: result
            })
        });
    }

 
    render() {
        return (
            <View style={styles.container}>
               

                <TouchableOpacity onPress={this._onPressButton2.bind(this)}>
                    <Text style={styles.hello}>{this.state.text}</Text>
                </TouchableOpacity>

            
            </View>
        );
    }
}

const styles = StyleSheet.create({
    hello: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
    },
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
    },
    welcome: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
    },
    instructions: {
        textAlign: 'center',
        color: '#333333',
        marginBottom: 5,
    },
});

Run the project, screen text appears river, river click on the text, the text becomes a river david; while spinning pop
"the Hello David"
6, Here Insert Picture Description
NA callback method to pass parameters through the promise realized.
Add method in the ToastExampleMoudle

   //最后一个参数是promise
    @ReactMethod
    public void textAndroidPromiseMethod(String msg, Promise promise){
        Toast.makeText(getReactApplicationContext(),msg,Toast.LENGTH_SHORT).show();
        String result = "david";
        //resolve代表正常运行,会走下面的then方法,如果是reject,则会走catch();
        promise.resolve(result);
    }

app.js file modification

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *
 * @format
 * @flow
 * @lint-ignore-every XPLATJSCOPYRIGHT1
 */

import React, {Component} from 'react';
//这里的ToastAndroid,是ToastExampleMoudle类中方法
//     @Override
//     public String getName() {
//         return "ToastForAndroid";
//     }
//     返回的名字。
import {
    Platform,
    StyleSheet,
    ToastAndroid,
    DeviceEventEmitter,
    Text,
    TouchableOpacity,
    View,
    NativeModules
} from 'react-native';

export default class App extends Component<Props> {
    constructor(props) {
        super(props);
        this.state = {
            text: "river",
            text2: "默认",
        }

    }

  
    _onPressButton3() {
        NativeModules.ToastForAndroid.textAndroidPromiseMethod("hello David").then((result) => {
            this.setState({
                text2: result
            })
        })
    }

 

    render() {
        return (
            <View style={styles.container}>
              <TouchableOpacity onPress={this._onPressButton3.bind(this)}>
                    <Text style={styles.hello}>{this.state.text2}</Text>
                </TouchableOpacity>
          </View>
        );
    }
}

const styles = StyleSheet.create({
    hello: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
    },
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
    },
    welcome: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
    },
    instructions: {
        textAlign: 'center',
        color: '#333333',
        marginBottom: 5,
    },
});

Operating results, the screen appears "default" word, click the word becomes the default david, while the pop-up spinning "hello david"

7, to pass an object js. We do not use callback, nor promise, another way.
Should do the following
js as an observer to be, want to inform the viewer, such as js life cycle, I would like to inform java, life cycle to what extent. There are a java method, but this method is not now call react when a page loads, I notice java call this method
we add in the code in ToastExampleMoudle

 private static final String MESSAGE = "MESSAGE";
   
    @Nullable
    @Override
    public Map<String, Object> getConstants() {
        //让js那边能够使用这些常量
        Map<String,Object> constants = new HashMap<>();
        constants.put(MESSAGE,"动脑 常量");
        return constants;
    }
      @ReactMethod
    public void onScaning() {
        WritableMap params = Arguments.createMap();
        params.putString("key","mydata");
        //通过java的方式发送一个对象事件,java通知js
        getReactApplicationContext().getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit("EventName", params);
    }

Look App.js file

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *
 * @format
 * @flow
 * @lint-ignore-every XPLATJSCOPYRIGHT1
 */

import React, {Component} from 'react';
//这里的ToastAndroid,是ToastExampleMoudle类中方法
//     @Override
//     public String getName() {
//         return "ToastForAndroid";
//     }
//     返回的名字。
import {
    Platform,
    StyleSheet,
    ToastAndroid,
    DeviceEventEmitter,
    Text,
    TouchableOpacity,
    View,
    NativeModules
} from 'react-native';

export default class App extends Component<Props> {
    constructor(props) {
        super(props);
        this.state = {
            text: "river",
            text2: "默认",
        }

    }

    componentDidMount(): void {
        //1,观察者对象     监听java  调用js
        //2,js去监听java
        //3.msg为我接收的数据
        DeviceEventEmitter.addListener("EventName", function (msg) {
            //获取到类里面的成员变量:
            let rest = NativeModules.ToastForAndroid.MESSAGE;
            //这个ToastAndroid是ReactNative自己带的。
            ToastAndroid.show("DeviceEventEmitter收到消息:" + "\n" + rest, ToastAndroid.SHORT)
        })

    }

  

//js作为一个被观察者,想去通知观察者,
// 比如js有生命周期,我想通知java,生命周期到了一个什么程度。
    //java里面有一方法,但这个方法并不是现在调用,当react某个页面
    //加载的时候,我在通知java这个方法进行调用
    _onPressButton4() {

        NativeModules.ToastForAndroid.onScaning();
    }

    render() {
        return (
            <View style={styles.container}>
               <TouchableOpacity onPress={this._onPressButton4.bind(this)}>
                    <Text style={styles.hello}>{this.state.text2}</Text>
                </TouchableOpacity>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    hello: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
    },
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
    },
    welcome: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
    },
    instructions: {
        textAlign: 'center',
        color: '#333333',
        marginBottom: 5,
    },
});

We click on the text, triggering _onPressButton4 method, then onScaning android method of triggers; call onScanning method when executing the following code generates an object
WritableMap params = Arguments.createMap(); params.putString("key","mydata");
We then getReactApplicationContext().getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) .emit("EventName", params);
called EventName event sends a name,
the final operating results: We run the project "default" text appears on the screen, click the "default" pop-up: "DeviceEventEmitter receive the message: mental and physical constants"

8, I put the complete code affixed:

package com.nativeapp;

import com.facebook.react.ReactPackage;
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;

//注册模块,注册到c
public class ExampleReactNativePackage implements ReactPackage {
//完成注入,需要被js调用java方法
    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
    //NativeModule添加到这个集合里,React Native通过这个方法知道当前有多少个需要给js调用的对象
        List<NativeModule> modules = new ArrayList<>();
        modules.add(new ToastExampleMoudle(reactContext));
        return modules;
    }

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
    //注意这里不能写return null;
        return Collections.emptyList();
    }
}

package com.nativeapp;

import com.facebook.react.ReactActivity;

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 "nativeapp";
    }
}

package com.nativeapp;

import android.widget.Toast;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.Nullable;
//
public class ToastExampleMoudle extends ReactContextBaseJavaModule {
    private static final String MESSAGE = "MESSAGE";
    public ToastExampleMoudle(ReactApplicationContext reactContext) {
        super(reactContext);
    }
    @Nullable
    @Override
    public Map<String, Object> getConstants() {
        //让js那边能够使用这些常量
        Map<String,Object> constants = new HashMap<>();
        constants.put(MESSAGE,"动脑 常量");
        return constants;
    }
    //通过js去弹出一个原生的吐丝
    @ReactMethod//要想这个方法暴露给js必须增加这个注解
    public void show(int duration){
        Toast.makeText(getReactApplicationContext(), "dongnao:" + duration, Toast.LENGTH_SHORT).show();
    }
    //1,具有回调参数的
    //2,callback是ReactNative里面的一个接口。这个接口只有一个方法。
    @ReactMethod
    public void testAndroidCallBack(String msg, Callback callback) {
        Toast.makeText(getReactApplicationContext(),msg,Toast.LENGTH_LONG).show();
        //invoke方法的参数是一个可变参数
        callback.invoke("david");
    }
    //最后一个参数是promise
    @ReactMethod
    public void textAndroidPromiseMethod(String msg, Promise promise){
        Toast.makeText(getReactApplicationContext(),msg,Toast.LENGTH_SHORT).show();
        String result = "david";
        //resolve代表正常运行,会走下面的then方法,如果是reject,则会走catch();
        promise.resolve(result);
    }
    @ReactMethod
    public void onScaning() {
        WritableMap params = Arguments.createMap();
        params.putString("key","mydata");
        //通过java的方式发送一个对象事件,java通知js
        getReactApplicationContext().getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit("EventName", params);
    }
    @Override
    public String getName() {
        return "ToastForAndroid";
    }

    @Override
    public boolean canOverrideExistingModule() {
        return true;
    }
}

package com.nativeapp;

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;
//注册java的模块,提前应用到缓存中心
public class MainApplication extends Application implements ReactApplication {
// reactNative主机
  private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
    @Override
    public boolean getUseDeveloperSupport() {
    //是否是开发者
      return BuildConfig.DEBUG;
    }

    @Override
    protected List<ReactPackage> getPackages() {
    //返回的是一个集合
      return Arrays.<ReactPackage>asList(
          new MainReactPackage(),
          //添加我们定义的ReactPackage
              new ExampleReactNativePackage()
      );
    }
    @Override
    protected String getJSMainModuleName() {
    //指向了程序的入口,index就是rn的主界面
      return "index";
    }
  };
  @Override
  public ReactNativeHost getReactNativeHost() {
    return mReactNativeHost;
  }

  @Override
  public void onCreate() {
    super.onCreate();
    SoLoader.init(this, /* native exopackage */ false);
  }
}

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *
 * @format
 * @flow
 * @lint-ignore-every XPLATJSCOPYRIGHT1
 */

import React, {Component} from 'react';
//这里的ToastAndroid,是ToastExampleMoudle类中方法
//     @Override
//     public String getName() {
//         return "ToastForAndroid";
//     }
//     返回的名字。
import {
    Platform,
    StyleSheet,
    ToastAndroid,
    DeviceEventEmitter,
    Text,
    TouchableOpacity,
    View,
    NativeModules
} from 'react-native';

export default class App extends Component<Props> {
    constructor(props) {
        super(props);
        this.state = {
            text: "river",
            text2: "默认",
        }

    }

    componentDidMount(): void {
        //1,观察者对象     监听java  调用js
        //2,js去监听java
        //3.msg为我接收的数据
        DeviceEventEmitter.addListener("EventName", function (msg) {
            //获取到类里面的成员变量:
            let rest = NativeModules.ToastForAndroid.MESSAGE;
            //这个ToastAndroid是ReactNative自己带的。
            ToastAndroid.show("DeviceEventEmitter收到消息:" + "\n" + rest, ToastAndroid.SHORT)
        })

    }

    _onPressButton() {
        /*调用ToastExampleMoudle类这个方法
         * @ReactMethod
         * public void show(int duration){
         *   Toast.makeText(getReactApplicationContext(), "dongnao:" + duration, Toast.LENGTH_SHORT).show();
         *   }
         */
        NativeModules.ToastForAndroid.show(1000);
    }

    _onPressButton2() {
        NativeModules.ToastForAndroid.testAndroidCallBack("hello David", (result) => {
            this.setState({
                text: result
            })
        });
    }

    _onPressButton3() {
        NativeModules.ToastForAndroid.textAndroidPromiseMethod("hello David").then((result) => {
            this.setState({
                text2: result
            })
        })
    }

//js作为一个被观察者,想去通知观察者,
// 比如js有生命周期,我想通知java,生命周期到了一个什么程度。
    //java里面有一方法,但这个方法并不是现在调用,当react某个页面
    //加载的时候,我在通知java这个方法进行调用
    _onPressButton4() {

        NativeModules.ToastForAndroid.onScaning();
    }

    render() {
        return (
            <View style={styles.container}>
                //this._onPressButton.bind(this),调用_onPressButton(),注意这里是es6写法
                <TouchableOpacity onPress={this._onPressButton.bind(this)}>
                    <Text style={styles.hello}>点击了</Text>
                </TouchableOpacity>

                <TouchableOpacity onPress={this._onPressButton2.bind(this)}>
                    <Text style={styles.hello}>{this.state.text}</Text>
                </TouchableOpacity>

                <TouchableOpacity onPress={this._onPressButton3.bind(this)}>
                    <Text style={styles.hello}>{this.state.text2}</Text>
                </TouchableOpacity>

                <TouchableOpacity onPress={this._onPressButton4.bind(this)}>
                    <Text style={styles.hello}>{this.state.text2}</Text>
                </TouchableOpacity>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    hello: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
    },
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
    },
    welcome: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
    },
    instructions: {
        textAlign: 'center',
        color: '#333333',
        marginBottom: 5,
    },
});

Guess you like

Origin blog.csdn.net/qczg_wxg/article/details/89227048