[JAVA] Commentaire ReactNative Android Bridge

une fonction

Native Modules Prenez Module, qui affiche une boîte de dialogue, à titre d'exemple.

[une fonction] 1, affichez la boîte de dialogue Android. (Création de fonction) 2, lorsque vous cliquez sur le bouton "OK" dans la boîte de dialogue, "true" s'affiche sur la console. (Notification d'événement) 3, lorsque le bouton "DATE" est cliqué, l'heure actuelle est affichée. (Rappeler)

DialogModule.java


public class DialogModule extends ReactContextBaseJavaModule {
    //Constructeur
    public DialogModule(@NonNull ReactApplicationContext reactContext) {
        super(reactContext);
    }
   //Quelque chose comme une balise pour appeler ce module
   @Override
    public String getName() {
        return "DialogModule";
    }

    //Peut définir des constantes de classe pouvant être utilisées dans RN
    public Map<String, Object> getConstants() {
        final Map<String, Object> constants = new HashMap<>();
        constants.put("SINGLE_BUTTON", "SINGLE");
        constants.put("DOUBLE_BUTTON", "DOUBLE");
        return constants;
    }

    //Fonction pour afficher une boîte de dialogue
    @ReactMethod
    public void showDialog(String message, String type) {
        if (type.equals("SINGLE")) {
            new AlertDialog.Builder(getCurrentActivity())
                    .setTitle("DialogModule")
                    .setMessage(message)
                    .setPositiveButton("CLOSE", (dialog, which) -> {
                        dialog.dismiss();
                    })
                    .show();
        } else {
            new AlertDialog.Builder(getCurrentActivity())
                    .setTitle("DialogModule")
                    .setMessage(message)
                    .setPositiveButton("OK", (dialog, which) -> {
                        sendEvent();
                    })
                    .setNegativeButton("CLOSE", (dialog, which) -> {
                        dialog.dismiss();
                    })
                    .show();
        }
    }

    //Une fonction qui affiche l'heure actuelle et rappelle
    @ReactMethod
    private void getCurrentTime(Callback callback) {
        Calendar calendar = Calendar.getInstance();
        callback.invoke(calendar.getTime().toString());
    }

    //Événement pour notifier que le bouton a été cliqué
    private void sendEvent() {
        WritableMap params = Arguments.createMap();
        params.putBoolean("click", true);
        getReactApplicationContext()
                .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit("onClick", params);
    }
}

Commentaire

getName Vous devez écrire la chaîne de caractères lors de l'appel de RN comme "DialogModule".

@Override
public String getName() {
    return "DialogModule";
}

getConstants Vous pouvez définir des constantes de classe Molue qui peuvent être utilisées à partir de RN.

public Map<String, Object> getConstants() {
    final Map<String, Object> constants = new HashMap<>();
    constants.put("SINGLE_BUTTON", "SINGLE");
    constants.put("DOUBLE_BUTTON", "DOUBLE");
    return constants;
}

@ReactMethod Vous pouvez définir les méthodes qui peuvent être utilisées à partir de RN. Si vous voulez exécuter le rappel, exécutez-le avec .invoke ().

@ReactMethod
private void getCurrentTime(Callback callback) {
    Calendar calendar = Calendar.getInstance();
    callback.invoke(calendar.getTime().toString());
}

ʻEvent (auditeur) ` Vous pouvez définir les événements qui peuvent être enregistrés dans RN.

//Définir la valeur de rappel
WritableMap params = Arguments.createMap();
params.putBoolean("click", true);
//Définir le nom de l'événement et la valeur de rappel
getReactApplicationContext()
    .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
    .emit("onClick", params);

Native UI Components Prenez une vue qui affiche un lecteur vidéo à titre d'exemple.

[une fonction] 1, affichez le lecteur vidéo. (Créer une vue) 2, recevez l'url du côté RN avec des accessoires et lisez la vidéo. 3, affichez le journal à la fin de la lecture. (Afficher la notification d'événement)

VideoViewManager.java


public class VideoViewManager extends SimpleViewManager<VideoView> {
    private Context context;

    //Quelque chose comme une balise pour appeler ce module
    @Override
    public String getName() {
        return "VideoView";
    }

    //Quelque chose comme un constructeur qui renvoie un instant de la vue à utiliser
    @Override
    protected VideoView createViewInstance(ThemedReactContext reactContext) {
        this.context = reactContext;
        return new VideoView(reactContext);
    }

    //Une fonction qui traite avec la valeur reçue par Props
    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
    @ReactProp(name="url")
    public void setVideoPath(VideoView videoView, String urlPath) {
        Uri uri = Uri.parse(urlPath);
        videoView.setMediaController(new MediaController(context));
        videoView.setVideoURI(uri);
        //Jouez dès qu'il est prêt à jouer
        videoView.setOnPreparedListener(mp -> {
            videoView.start();
        });
        //Rappelez "onFinish" des accessoires à la fin de la lecture.(notification)
        videoView.setOnCompletionListener(mp -> {
            ReactContext reactContext = (ReactContext)context;
            
            WritableMap event = Arguments.createMap();
            event.putString("message", "onDirectEvent");
            reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(videoView.getId(),"onDirectEvent",event);

            WritableMap event2 = Arguments.createMap();
            event2.putString("message", "onBubblingEvent");
            reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(videoView.getId(),"onBubblingEvent",event2);
        });
        videoView.getDuration();
    }

    @Override
    public Map<String, Object> getExportedCustomDirectEventTypeConstants() {
        return MapBuilder.<String, Object>builder()
                .put("onDirectEvent", MapBuilder.of("registrationName", "onDirectEvent"))
                .build();
    }

    @Override
    public Map<String, Object> getExportedCustomBubblingEventTypeConstants() {
        return MapBuilder.<String, Object>builder()
                .put("onBubblingEvent", MapBuilder.of("phasedRegistrationNames",
                                    MapBuilder.of(
                                            "bubbled", "onBubble",
                                            "captured", "onCapture")))
                .build();
    }
}

Commentaire

getName La chaîne de caractères lors de l'appel depuis RN doit être décrite comme "VideoView".

@Override
public String getName() {
    return "VideoView";
}

@ReactProp Méthode Setter qui reçoit les Props of View Le nom de la méthode lui-même peut être n'importe quoi @ReactProp (nom =" nom d'accessoires ") public void setProp (Vue type de vue, valeur de type Props)

@ReactProp(name="url")
public void setVideoPath(VideoView videoView, String urlPath) {
        // ...
}

createViewInstance Une fonction qui renvoie une instance de View

@Override
protected VideoView createViewInstance(ThemedReactContext reactContext) {
    return new VideoView(reactContext);
}

«Notification d'événement» Vous pouvez définir le rappel pour les accessoires.

Inscription à l'événement

Il existe deux méthodes pour enregistrer des événements. ・ GetExportedCustomDirectEventTypeConstants ・ GetExportedCustomBubblingEventTypeConstants

getExportedCustomDirectEventTypeConstants Notifier un accessoire avec un événement. Comment s'inscrire MapBuilder.builder (). Put (" nom de l'événement ", MapBuilder.of (" registrationName "," props name ")). Build ();

getExportedCustomBubblingEventTypeConstants Deux accessoires peuvent être notifiés dans un événement. Comment s'inscrire MapBuilder.builder (). Put (" nom de l'événement ", MapBuilder.of (" phasedRegistrationNames ", MapBuilder.of (" bubbled "," props name 1 "," capturé "," props name 2 "))). Build ();

//Fonction d'enregistrement d'un événement 1
@Override
public Map<String, Object> getExportedCustomDirectEventTypeConstants() {
    return MapBuilder.<String, Object>builder()
            .put("onDirectEvent", MapBuilder.of("registrationName", "onDirectEvent"))
            .build();
}

//Fonction d'enregistrement d'un événement 2
@Override
public Map<String, Object> getExportedCustomBubblingEventTypeConstants() {
    return MapBuilder.<String, Object>builder()
            .put("onBubblingEvent", MapBuilder.of("phasedRegistrationNames",
                                MapBuilder.of(
                                        "bubbled", "onBubble",
                                        "captured", "onCapture")))
            .build();
}

Appelez receiveEvent à l'endroit où vous souhaitez être averti receiveEvent (" ID de vue "," nom de l'événement ", valeur de rappel)

// ...
ReactContext reactContext = (ReactContext)context;
//Processus de notification de l'événement 1"onDirectEvent"un événement
WritableMap event = Arguments.createMap();
event.putString("message", "onDirectEvent");
reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(videoView.getId(),"onDirectEvent",event);

//Processus de notification de l'événement 2"onBubblingEvent"un événement
WritableMap event2 = Arguments.createMap();
event2.putString("message", "onBubblingEvent");
reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(videoView.getId(),"onBubblingEvent",event2);
// ...

Du côté RN, l'événement est notifié comme suit

<VideoView
      onDirectEvent={({ nativeEvent }) => console.log(nativeEvent.message)} // onDirectEvent
      onCapture={({ nativeEvent }) => console.log(nativeEvent.message)} // onBubblingEvent
      onBubble={({ nativeEvent }) => console.log(nativeEvent.message)} // onBubblingEvent
/>

Enregistrement du module et du composant d'interface utilisateur

Enregistrez le module et le composant d'interface utilisateur créés comme suit

ExamplePackage.java


public class ExamplePackage implements ReactPackage {
    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.<ViewManager>singletonList(
                //Ajouter à mesure que les composants de l'interface utilisateur augmentent
                new VideoViewManager()
        );
    }

    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext
            return Collections.<ViewManager>singletonList(
                //Ajouter en tant que modules supplémentaires
                new DialogModule(reactContext)
        );
    }
}

Enregistrez le package créé dans getPackages dans MainApplication.java

MainApplication.java


@Override
protected List<ReactPackage> getPackages() {
      List<ReactPackage> packages = new PackageList(this).getPackages();
           //Ajouter à mesure que le nombre de paquets augmente
           packages.add(new ExamplePackage());
      return packages;
}

Côté RN Native Modules

Dialog.jsx


import React from 'react';
import { NativeModules } from 'react-native';
//Valeur de retour de la fonction getName("DialogModule")Spécifier
DialogModule = NativeModules.DialogModule;

const Dialog = () => {
  const [date, setDate] = React.useState("");

  React.useEffect(() => {
    const eventEmitter = new NativeEventEmitter(DialogModule);
    eventEmitter.addListener('onClick', (event) => {
       console.log(event.change) // "true"
    });
  }, [])

  return (
    <>
      <TouchableOpacity onPress={() => DialogModule.showDialog('SINGLE BUTTON', DialogModule.SINGLE_BUTTON)}>
        <Text>SINGLE BUTTON Dialog</Text>
      </TouchableOpacity>
      <TouchableOpacity onPress={() => DialogModule.showDialog('DOUBLE BUTTON', DialogModule.DOUBLE_BUTTON)}>
        <Text>DOUBLE BUTTON Dialog</Text>
      </TouchableOpacity>
      <TouchableOpacity onPress={() => DialogModule.getCurrentTime(time => setDate(time))}>
        <Text>DATE</Text>
      </TouchableOpacity>
        <Text>CURRENT DATE:</Text>
      <Text>[ {date} ]</Text>
    </>
  )
}

export default Dialog

Native UI Components

VideoView.jsx


import React from 'react';
import { requireNativeComponent } from 'react-native';
VideoView = requireNativeComponent('VideoView');

const VideoView = () => {

  return (
    <>
      <VideoView 
        style={{ width: '100%', height: '100%' }}
        url="https://www.radiantmediaplayer.com/media/bbb-360p.mp4"
        onDirectEvent={({ nativeEvent }) => console.log(nativeEvent.message)}
        onCapture={({ nativeEvent }) => console.log(nativeEvent.message)}
        onBubble={({ nativeEvent }) => console.log(nativeEvent.message)} />
    </>
  )
}

export default VideoView

prime

Lorsque vous souhaitez appeler la fonction implémentée dans UI Component à partir du module

ExamplePackage.java


public class ExamplePackage implements ReactPackage {
    private ExampleViewManager instance;
    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.<ViewManager>singletonList(
                instance
        );
    }

    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext
            instance = new ExampleViewManager();
            return Collections.<ViewManager>singletonList(
                //Passer une instance de ViewManager au module
                //Après cela, vous pouvez appeler la méthode de l'instance à partir de la fonction définie dans le module.
                new ExampleModule(reactContext, instance)
        );
    }
}

finalement

En ce qui concerne la partie bridge d'Android, j'ai eu beaucoup de problèmes avec uniquement des articles en anglais et des exemples de code qui ne fonctionnaient pas. Comme je n'ai pas eu beaucoup de temps pour écrire un article, il peut y avoir des omissions ou des erreurs, veuillez donc utiliser le contenu de l'article comme référence.

Ensuite, l'article sur le 20e jour du calendrier de l'avent React Native est le "test Talk about AB" de @ duka: tada:

Recommended Posts

Commentaire ReactNative Android Bridge
Comment écrire React Native Bridge ~ Version Android ~
Utiliser le code natif sur Android
Utilisation du composant d'interface utilisateur natif avec React Native (version Android)
[Android] Notes sur xml
Construction d'un environnement Android que même les singes peuvent comprendre [React Native]
Utilisez Java inclus avec Android Studio pour créer React Native
Personnaliser la vue de liste sur Android
Bibliothèque de transmission en plusieurs parties sur Android
Utiliser la communication série sur Android
Développement d'applications ROS sur Android