When we use React Native for hybrid development, we must communicate and interact with React Native natively. This article is about sharing several ways for native modules and JS to pass data.
The overall steps can be divided into the following points:
- Define the Module class on the native side, inherit the ReactContextBaseJavaModule, and define the interactive method in the Module class.
- Define the Package class, inherit ReactPackage, and add Module instances to the collection.
- In the ReactApplication inherited by Android, the callback implements the getPackages method and adds the Package instance to the collection under getPackages.
The following is the example code of the Mudule class. In order to facilitate everyone's understanding, I posted all the codes and explained them one by one.
import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; public class ToastExample extends ReactContextBaseJavaModule{ private static final String LONG_TIME = "LONG"; private static final String SHORT_TIME = "SHORT"; private static final String MESSAGE = "MESSAGE"; public ToastExample(ReactApplicationContext reactContext) { super(reactContext); } @Override public String getName() { return "ToastForAndroid"; } @ReactMethod public void getDataFromIntent(Callback callback){ try{ Activity currentActivity=getCurrentActivity(); String result =().getStringExtra("data"); if((result)){ ("no_data"); }else{ (result); } }catch (Exception e){ ("error"); } } @Override public Map<String, Object> getConstants() { //Let js use these constants Map<String,Object> constants = new HashMap<>(); (LONG_TIME, Toast.LENGTH_LONG); (SHORT_TIME,Toast.LENGTH_SHORT); (MESSAGE,"getConstants"); return constants; } @ReactMethod public void show(int duration){ (getReactApplicationContext(),"message:"+duration,duration).show(); } @ReactMethod public void sendEvent(){ onScanningResult(); } @ReactMethod public void testAndroidCallbackMethod(String msg, Callback callback){ (getReactApplicationContext(),msg,Toast.LENGTH_LONG).show(); ("abc"); } @ReactMethod public void textAndroidPromiseMethod(String msg, Promise promise){ (getReactApplicationContext(),msg,Toast.LENGTH_SHORT).show(); String result="Xie Hanjie"; (result); } public void onScanningResult(){ WritableMap params = (); ("key", "myData"); sendEvent(getReactApplicationContext(),"EventName",params); } public static void sendEvent(ReactContext reactContext, String eventName, @Nullable WritableMap params) { ().emit(eventName, params); } public void nativeCallRn(){ onScanningResult(); } @Override public boolean canOverrideExistingModule() { return true; } }
In the above Module code, the name returned by the getName() method is that the name returned in the RN code is required to call the method of the class. The method under @ReactMethod annotation is our custom method, indicating that this method can be called by rn. As for the above four forms of methods and other steps, it will be explained in detail.
The custom ReactPackage code is as follows:
import ; import ; import ; import ; import ; import ; import ; public class ExampleReactNativePackage implements ReactPackage{ public ToastExample toastExample; @Override public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) { List<NativeModule> modules = new ArrayList<>(); toastExample=new ToastExample(reactContext); (toastExample); return modules; } @Override public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) { return (); } }
This step is very simple, just add the ToastExample class above to NativeModule
Then the third step is also very simple, the code is as follows
import ; import ; import ; import ; import ; import ; import ; public class MyApplication extends Application implements ReactApplication{ public static final ExampleReactNativePackage exampleReactNativePackage=new ExampleReactNativePackage(); private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { @Override public boolean getUseDeveloperSupport() { return ; } @Override protected List<ReactPackage> getPackages() { return Arrays.<ReactPackage>asList( new MainReactPackage(), exampleReactNativePackage ); } }; @Override public ReactNativeHost getReactNativeHost() { return mReactNativeHost; } }
This is not just adding the ExampleReactNativePackage to the ReactPackage, it is also very simple.
For this reason, the entire Android native has been written. Next is to write a js end, and the following is an example of a js end: (To put nonsense, I usually like to post all the codes to explain them one by one, which is more coherent)
import React from 'react'; import { AppRegistry, StyleSheet, Text, View, TouchableOpacity, ToastAndroid, NativeModules, DeviceEventEmitter } from 'react-native'; export default class HelloWorld extends { constructor(props){ super(props); ={ text1:'ToastForAndroid', text2:'testAndroidCallbackMethod', text3:'textAndroidPromiseMethod', text4:'DeviceEventEmitter', text5:'getValue', data:'no_data', } } componentWillMount() { ('EventName', function (msg) { (msg); let rest=; ("DeviceEventEmitter received the message:" + "\n" + rest, ) }); ((result)=>{ ({data:result}); }); } render() { return ( <View style={}> <Text>{}</Text> <TouchableOpacity onPress={this._onPressButton.bind(this)}> <Text style={}>{.text1}</Text> </TouchableOpacity> <TouchableOpacity onPress={this._onPressButton2.bind(this)}> <Text style={}>{.text2}</Text> </TouchableOpacity> <TouchableOpacity onPress={this._onPressButton3.bind(this)}> <Text style={}>{.text3}</Text> </TouchableOpacity> <TouchableOpacity onPress={this._onPressButton4.bind(this)}> <Text style={}>{.text4}</Text> </TouchableOpacity> <TouchableOpacity onPress={this._onPressButton5.bind(this)}> <Text style={}>{.text5}</Text> </TouchableOpacity> </View> ) } _onPressButton(){ (1000); } _onPressButton2(){ ("HelloJack",(result)=>{ ({text:result}); }); } _onPressButton3(){ ("abcx").then((result)=>{ ({text3:result}); }).catch((error)=>{ ({text:'error'}); }) } _onPressButton4(){ (); } _onPressButton5(){ (, ) } } var styles = ({ container: { flex: 1, justifyContent: 'center', flexDirection: 'column', }, hello: { fontSize: 20, textAlign: 'center', margin: 10, }, }); ('HelloWorlds', () => HelloWorld);
This is the call instance of the entire js side. In the React Naitve layer, the RN side can adjust the native method through NativeModules.[module name].[Method name], and the passed parameters can also be obtained through the RN side through NativeModules.[module name].[Parameter name]. The specific usage is as above code.
For native calls to the methods in React Native, we can use RCTDeviceEventEmitter method. This method is equivalent to broadcasting in Android. The specific corresponding native code is as follows:
();
It is also coherent with the above code.
Finally, summarize the four ways of interaction
The first one is the simplest, as in the above code
@ReactMethod public void show(int duration){ (getReactApplicationContext(),"message:"+duration,duration).show(); }
That is, use the ReactMethod annotation method to call native
Callback callback method, like the above code
@ReactMethod public void testAndroidCallbackMethod(String msg, Callback callback){ (getReactApplicationContext(),msg,Toast.LENGTH_LONG).show(); ("abc"); }
The corresponding js code is
_onPressButton2(){ ("HelloJack",(result)=>{ ({text:result}); }); }
That is, you pass in parameters to operate and then give you the callback result
The callback method is similar to RxJava. Complex code structures can be converted into short and easy-to-read code through chaining. As shown in the above code
@ReactMethod public void textAndroidPromiseMethod(String msg, Promise promise){ (getReactApplicationContext(),msg,Toast.LENGTH_SHORT).show(); String result="Xie Hanjie"; (result); }
The corresponding js code is
_onPressButton3(){ ("abcx").then((result)=>{ ({text3:result}); }).catch((error)=>{ ({text:'error'}); }) }
The JS side obtains the Promise data through the then interface, and returns error information when the execution error is performed.
Through event method: RCTDeviceEventEmitter, generally native calls React Native, which is equivalent to broadcast. The corresponding code above is as follows:
public static void sendEvent(ReactContext reactContext, String eventName, @Nullable WritableMap params) { ().emit(eventName, params); }
The corresponding js code is
('EventName', function (msg) { (msg); let rest=; ("DeviceEventEmitter received the message:" + "\n" + rest, ) });
Native sends native events and then React Native registers to listen to get information.
Here is an example of our actual combat, which is to start the RN interface and pass data. How to do it? Beginners at the beginning still couldn't react at once. The starting point was very simple. Just use our examples above.
First, native startup code
Intent intent=new Intent(,); ("data","HelloJack"); startActivity(intent);
The final thing is to add it to the ToastExample class above
@ReactMethod public void getDataFromIntent(Callback callback){ try{ Activity currentActivity=getCurrentActivity(); String result =().getStringExtra("data"); if((result)){ ("no_data"); }else{ (result); } }catch (Exception e){ ("error"); } }
Then get it on the RN side
((result)=>{ ({data:result}); });
Similarly, please refer to other situationsRN's Android: Inter-call and data transfer between native interface and React interface, This is also one of my references.
Finally, I present the source code that everyone is most looking forward to/jack921/ReactNativeParamIf you don't understand anything, just open source code
The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.