Dart ouvert à canal super autochtone, la faim, que les meilleures pratiques à travers les plates-formes

Auteur | Yong Assuner lumière, légumes grognent, Qing exécutif, Ze Gua

Zebian | Tu Min

Produit | Blog RPSC

avant-propos

Flutter comme le plus chaud moment de la technologie multi-plateforme qui offre des performances comparables à une expérience application native. Flutter RN également comparé sa propre couche renderObject et obtenir le rendu, « presque » résolu complètement le problème de la cohérence multi-terminal, de sorte qu'une mise en uvre réellement efficace du code Dart « L'écriture d'un courant partout, » a presque doublé améliorer le développement qui se déplace l'efficacité des briques.

Pourquoi dire avant « presque », bien que Flutter nous offre un programme de développement rapide pour construire l'interface utilisateur et de l'interaction, mais implique l'utilisation des capacités de la plate-forme autochtones telles que pousser, le positionnement, Bluetooth et ainsi de suite, ne peut être « Quxianjiuguo » avec la réalisation du canal, que nous avons inévitablement à écrire du code et font partie du code de Dart natif faire « la technologie d'amarrage », ce qui nuit un peu la cohérence cross-plate-forme « parfaite ». De plus, la plupart des applications de l'entreprise ne sont pas complètement rétablie Flutter App, le plus souvent, la page d'une entreprise de développement Flutter et, éventuellement, pour compiler le produit en tant que module intégré dans le projet principal. Le principal projet d'origine a eu beaucoup de bons outils bibliothèque ou commerciale, comme il peut être puissant, la mise en cache locale pour optimiser la bibliothèque de la bibliothèque de réseau un grand nombre, il pourrait être une pleine utilisation de, certainement, les capacités autochtones nécessitent l'utilisation de la phase beaucoup plus que la possibilité d'étendre leur gamme de plates-formes, les définitions de canal et de l'utilisation deviennent plus haute fréquence.

De nombreux développeurs ont utilisé le canal, en particulier Dart Méthode appel canal code natif. Dans Dart côté, nous pouvons instancier un objet canal:

const statique MethodChannel examleChannel = const MethodChannel ( 'ExamplePlugin');

Utilisez le canal appelle la méthode native:

version finale String = await examleChannel.invokeMethod ( 'nativeMethodA', { "a": 1, "b": "abc"});

Dans la plate-forme iOS, ObjC besoin d'écrire le code:

FlutterMethodChannel * = canal; ;

Dans la plate-forme Android, vous avez besoin d'écrire du code Java:

 ExamplePlugin public class outils MethodCallHandler { / ** Enregistrement Plugin. * / public static void registerWith (registraire registraire) { canal MethodChannel final = nouveau MethodChannel (registrar.messenger, "ExamplePlugin"); channel.setMethodCallHandler (nouveau ExamplePlugin); } @Override onMethodCall public void (appel MethodCall, résultat Résultat) { si (call.method.equals ( "nativeMethodA")) { // ... } } }

On peut voir de ce qui précède, l'utilisation du canal présente les inconvénients suivants:

  • Nom du canal, le nom de méthode pour appeler une chaîne codée en dur;

  • Channel uniquement un bloc de code unique est appelé paramètres correspondant à une chaîne entière définissent un seul objet, méthode de classe native existante ne peut pas être appelé, mais pas une combinaison de plusieurs appel de méthode native.

  • Dans les blocs correspondants de la chaîne de code natif, encore besoin de supprimer manuellement les paramètres correspondants pour l'appel réel de la méthode clé, puis retourne la valeur de retour à la flèche du paquet.

  • Canal définir un appel de méthode native, vous devez maintenir fléchette, ObjC, code Java tripartite;

  • Lorsque le débogage Flutter, le code natif est pas pris en charge par la charge thermique, modifier les besoins en code natif pour être projet réexécution;

  • appel de canal peut couvrir beaucoup de morceaux de capacité native, méthode code de traitement natif ne doit pas être excessive, et dépend généralement de la bibliothèque tripartite, une pluralité d'entretien des canaux est décentralisé.

  • Poursuivre l'analyse, nous avons Cognition:

  • Multi-plateforme, situez coder en dur une méthode est absolument inévitable;

  • dans le bloc correspondant de la chaîne de code natif, la méthode appelle la véritable clé est indispensable;

  • Méthode appel doit prendre en charge les paramètres variables.

  • À cette fin, nous avons mis en place un Dart Super Channel au Native - adn, en essayant de résoudre les nombreuses lacunes de l'utilisation et l'entretien du canal, a principalement les capacités et les caractéristiques suivantes:

  • Utilisez tous les appels de méthode de code natif fléchette une classe, canal moyenne de code natif peut être écrit dans un fichier source de fléchettes;

  • Appeler plusieurs méthodes natives peuvent être combinés pour déterminer la valeur de retour, à l'appui contexte d'appel, chaîne d'appel;

  • paramètres de séquence d'invocation de méthode native directement dans la gamme de longueur indéfinie, la séquence naturelle paramètre d'appel automatiquement le déballage;

  • Prise en charge native charge de code à chaud, l'expérience de développement continu;

  • Faciliter la maintenance du code.

  • Utilisation d'adn

    Dans le code Dart adn:

    • NativeContext classe définie, de façon à exécuter le code Dart, la description du contexte des appels de code natif (de la pile d'appel); context.execute dernier appel effectué code natif correspond à la plate-forme et renvoie le résultat.

    • NativeObject définie classe, pour identifier la variable native. NativeObject objet de l'appelant peut invoquer réside le contexte d'appel de la méthode NativeContext passer procédé et la liste du tableau d'argument de nom de méthode, obtenu au moyen de la valeur de retour d'objets NativeObject.

    L'API de NativeContext est le même. Les détails suivants avant d'appeler ObjC par ObjCContext, la différence introduit JAVA appel JAVAContext.

    Dart appel ObjC

    ObjCContext que la mise en uvre pratique de la plate-forme iOS.

    1. Soutenir le contexte des appels

    (1) retourne la valeur de l'appelant en tant que

    code de ObjC

    NSString * versionString =; // renvoie versionString par le canal

    code de Dart

    ObjCContext contexte = ObjCContext; NativeObject UIDevice = context.classFromString ( 'UIDevice'); Dispositif NativeObject = UIDevice.invoke (méthode: 'currentDevice'); NativeObject version = device.invoke (méthode: 'VersionSystème'); context.returnVar = Version; // retourne la valeur finale peut être réglée à être omis, la référence 3 // accès direct aux résultats de l'indigène var versionString = await context.execute;

    (2) une valeur de retour en tant que paramètre

    code de ObjC

    NSString * versionString =; NSString * plate-forme = @ "iOS-"; versionString =; // renvoie versionString par le canal

    code de Dart

    ObjCContext contexte = ObjCContext; NativeClass UIDevice = context.classFromString ( 'UIDevice'); Dispositif NativeObject = UIDevice.invoke (méthode: 'currentDevice'); NativeObject version = device.invoke (méthode: 'VersionSystème'); . Plateforme NativeObject = context.classFromString ( "NSString") invocation (méthode: 'stringWithString:', args :); version = platform.invoke (méthode: 'stringByAppendingString:', args :); context.returnVar = Version; // retourne la valeur finale peut être réglée à être omis, la référence 3 // accès direct aux résultats de l'indigène var versionString = await context.execute;

    2. appelle chaîne de soutien

    code de ObjC

    NSString * versionString =; NSString * plate-forme = @ "iOS-"; versionString =; // renvoie versionString par le canal

    code de Dart

    ObjCContext contexte = ObjCContext; NativeObject version = context.classFromString ( 'UIDevice') invocation (méthode: 'currentDevice') invocation (méthode: 'VersionSystème') ..; Version = context.classFromString ( "NSString") Invoke (méthode: 'stringWithString:', args :) .invoke (méthode: 'stringByAppendingString:', args :) .; context.returnVar = Version; // retourne la valeur finale peut être réglée à être omis, la référence 3 // accès direct aux résultats de l'indigène var versionString = await context.execute;

    À propos de Contexte valeur de retour finale

    context.returnVar drapeau d'achèvement est la valeur renvoyée contexte d'exécution final:

  • Réglage context.returnVar: rendements variables autochtones du NativeObject correspondant

  • N'est pas réglé context.returnVar: Invoke exécuté à la dernière, si la valeur de retour, pour revenir à la valeur finale du contexte, aucune valeur de retour retournée est une valeur nulle;

  • ObjCContext contexte = ObjCContext; context.classFromString ( 'UIDevice') invocation (méthode: 'currentDevice') invocation (méthode: 'VersionSystème') ..; // accès direct aux résultats de l'indigène var versionString = await context.execute;

    3. Soutien objet une utilisation rapide JSON est instancié

    Peut-être il y a des moments où nous devons utiliser JSON instancier directement un objet.

    code de ObjC

    ClassA * objectA =; objectA.a = 1; objectA.b = @ "sss";

    En général, quand écriture.

    code de Dart

    ObjCContext contexte = ObjCContext; . NativeObject objectA = context.classFromString ( 'ClassA') invocation (méthode: 'new'); objectA.invoke (méthode: 'Seta:', args :); objectA.invoke (méthode: 'SetB:', args :);

    Il peut également être généré à partir du JSON

    ObjCContext contexte = ObjCContext; NativeObject objectA = context.newNativeObjectFromJSON ({ 'a': 1, 'b': 'sss'}, 'ClassA');

    Dart appel Java

    JAVAContext ne sera dans la mise en uvre effective du système Android. JAVAContext a toutes les caractéristiques de l'air ObjCContext Dart de ObjC.

    • contexte appel de soutien

    • Soutenir les appels chaînés

    • Soutenir les objets instanciés avec JSON

    En outre, un appui supplémentaire du constructeur d'une instance d'objet

    4. Structure de support en utilisant l'instance d'objet raccourci

    code Java

    plate-forme String = new String ( "android");

    code de Dart

    NativeObject version = contexte .newJavaObjectFromConstructor ( 'java.lang.String',)

    organisation rapide de code double face

    Il fournit un moyen rapide d'effectuer l'initialisation et le contexte.

    statique avenir < objet >  traversingNative (ObjCContextBuilder (ObjCContext objcContext), JAVAContextBuilder (JAVAContext javaContext)) {async NativeContext nativeContext; si (Platform.isIOS) { nativeContext = ObjCContext; ObjCContextBuilder (nativeContext); } Else if (Platform.isAndroid) { nativeContext = JAVAContext; JAVAContextBuilder (nativeContext); } retour executeNativeContext (nativeContext); }

    Vous pouvez écrire rapidement les deux extrémités de l'appel natif

    PlateformeVersion = await Dna.traversingNative ((contexte ObjCContext) { NativeObject version = context.classFromString ( 'UIDevice') invocation (méthode: 'currentDevice') invocation (méthode: 'VersionSystème') ..; Version = context.classFromString ( "NSString") Invoke (méthode: 'stringWithString:', args :) .invoke (méthode: 'stringByAppendingString:', args :) .; context.returnVar = Version // la phrase peut être omise }, (Contexte JAVAContext) { . NativeObject VERSIONID = context.newJavaObjectFromConstructor ( 'com.example.dna_example.DnaTest',) .invoke (méthode: 'getDnaVersion') invocation (méthode: 'getVersion'); NativeObject version = context.newJavaObjectFromConstructor ( 'java.lang.String',) .invoke (méthode: "concat", args :); context.returnVar = Version // la phrase peut être omise });

    adn Introduction Principes

    mise en uvre de base

    adn ne comporte pas fléchette cible pour convertir objet natif, ne se soucient pas du cycle de vie des objets autochtones, mais plutôt se concentrer sur le contexte de décrire l'appel de méthode native, appeler une méthode native dans le contexte par canal exécuter, la pile d'appel sous la forme de JSON passer pour les appels de résolution dynamique native.

    Comme précédemment fléchette dans le code:

    ObjCContext contexte = ObjCContext; NativeObject version = context.classFromString ( 'UIDevice') invocation (méthode: 'currentDevice') invocation (méthode: 'VersionSystème') ..; Version = context.classFromString ( "NSString") Invoke (méthode: 'stringWithString:', args :) .invoke (méthode: 'stringByAppendingString:', args :) .; context.returnVar = Version; // retourne la valeur finale peut être réglée à être omis, la référence 3 // accès direct aux résultats de l'indigène var versionString = await context.execute;

    NativeContext méthode d'exécution, l'appel réel:

    statique avenir < objet >  executeNativeContext (contexte NativeContext) de {async retourner _channel.invokeMethod await ( 'executeNativeContext', context.toJSON); }

    Dans la méthode de la executeNativeContext native exécutée, le JSON reçu correspondant est le suivant:

    { "_ObjectJSONWrappers" :, "ReturnVar": { "_ObjectId": "_objectId_WyWRIsLl" }, "_InvocationNodes": }

    Nous maintenons un Natif objectsInContextMap, à objectId comme la clé de valeurs d'objets autochtones.

    _InvocationNodes appelle les méthodes de contexte, voir l'individu.

    Ici appeler dynamiquement, retourner l'objet à returnVar stocké dans « _objectId_KNWtiPuM » pour mettre la clé dans objectsInContextMap:

    { "ReturnVar": { "_ObjectId": "_objectId_KNWtiPuM" }, "Objet": { "_ObjectId": "_objectId_qyfACNGb", "ClsName": "UIDevice" }, "Méthode": "currentDevice" },

    objectId d'appel de méthode où l'objet est « _objectId_KNWtiPuM », est une valeur de retour de la méthode, sortie de la objectsInContextMap continue pour l'invocation de dynamique returnVar object_id stockée comme nouvelle valeur de retour clé.

    { "ReturnVar": { "_ObjectId": "_objectId_haPktBlL" }, "Objet": { « _ObjectId »: « _objectId_KNWtiPuM » // trouvera l'objet réel objectsInContextMap }, « Méthode »: « VersionSystème » }

    Lorsque la méthode a des paramètres, pack automatique et déballer, tels que int < - > NSNumber .., 15 types de paramètres non-canal si spécifié, est NativeObject, nous allons trouver des objets de objectsInContextMap dans, mettre la liste des arguments réels:

    { "Objet": { "_ObjectId": "_objectId_UiCMaHAN" }, "Méthode": "stringByAppendingString:", "args" :, "ReturnVar": { "_ObjectId": "_objectId_WyWRIsLl" }

    Si la returnVar finale, sera l'objet correspondant au returnVar objectId savoir objectsInContextMap, comme la valeur de retour du canal de rappel arrière. Si non défini, la dernière invocation prend la valeur de retour (le cas échéant).

    détails d'implémentation Android

    Dynamic Invocation

    Android Mises en uvre principalement basé sur la réflexion, passé au-dessus par noeud adn appel d'information méthodes connexes.

    organigramme Android

    Le procédé général ci-dessus, pour générer le côté appelant correspondant à flottement « nuds de méthode » de la chaîne, et en analysant « invocation de nuds », l'événement va générer correspondante réfléchie.

    Par exemple, lorsque la méthode est appelée lorsqu'une fin Flutter:

    NativeObject VERSIONID = contexte .newJavaObjectFromConstructor ( 'me.ele.dna_example.DnaTest',) .invoke (méthode: 'getDnaVersion');

    Nous générons la structure primaire du canal entrant Shengduan manière unifiée à l'intérieur de ces liens correspondant sera suivi par l'appel initial réfléchissant selon les informations de noeud Shengduan.

    Est stocké dans le nom du nud de la classe où les méthodes de la classe, le nom de la méthode, type de paramètres et d'autres informations connexes. Sur cette base, nous pouvons par la réflexion, l'acquisition de tous le même nom de classe pour le nom de la méthode de la méthode, les paramètres de type et d'alignement, la méthode obtient une cible, de manière à atteindre pour atteindre surchargé.

    Appels de méthode pour obtenir des résultats sera de retour en arrière, comme l'appelant enchaînée appeler un nud pour une utilisation, pour finalement obtenir les résultats au Flutter prendra fin.

    La confusion court-circuitant

    difficulté

    Il y a aussi une difficulté Dna avez besoin de surmonter est la façon de contourner la confusion. Version de sortie du code sera confus, les classes d'origine, les méthodes, les variables seront rebaptisés. Au-dessus, Dna Le principe est le mode de livraison de côté nom de classe et flutter informations de natif Android à la fin, faire des appels de méthode par réflexion, version La version du compilateur, les noms de classe et de méthode sont source de confusion, la méthode ne sera pas trouvée.

    Si vous ne pouvez pas résoudre le problème confondent souvent, alors Dna ne peut rester dans la phase de débogage, pas vraiment l'utilisation en ligne.

    plan

    Nous avons souvent confondu par des règles personnalisées, préciser les méthodes nécessaires ne doivent pas être confondus, mais ici n'est pas applicable. Pour les raisons suivantes:

  • Nous ne pouvons pas permettre aux utilisateurs de personnaliser les règles de confusion pour spécifier la méthode locale est à ne pas confondre. Cela endommagerait la sécurité du code, et l'opération est trop compliquée.

  • Les règles personnalisées sont généralement seul moyen d'éviter la confusion est à ne pas confondre avec le nom, mais ne peuvent pas affecter les paramètres, à moins que la classe des paramètres anti-aliasing aussi. Adn être mis en uvre par le type de paramètre fonction de rechargement, de sorte que ce régime est inacceptable.

  • Nous voulons que le programme devrait avoir les caractéristiques suivantes:

    • Facile à utiliser, configurer une confusion des règles éviter personnalisé

    • Coffre-fort, mini-invasive

    En réponse à ces exigences, nous vous proposons plusieurs options:

  • Anti être atteint par un lien cartographie

  • En encapsulant l'ensemble de la chaîne d'appel pour diffuser protocole de couche native, le code proxy est ensuite généré par une manière dynamique à l'invocation de méthode corps de boîtier de la chaîne

  • A titre de commentaire, pour générer la méthode proxy pour chaque appel de méthode au moment de la compilation

  • À l'heure actuelle, nous utilisons trois programmes fonctionnent sa granulométrie plus fine, plus propice à la réutilisation.

    L'opération est source de confusion pour le fichier de .classes, après sa compilation d'exécution javac. Nous avons donc lors de la compilation, le code est numérisé, la méthode de génération de fichiers proxy, la méthode cible de stockage d'informations ensemble, puis la sortie. Lors de l'exécution, on trouve les documents proxy, l'accès à la méthode proxy que la méthode par laquelle des informations, effectuer la façon dont nous voulons exécuter la cible par une méthode proxy. la mise en uvre spécifique, nous avons besoin d'être mis en uvre par l'APT (traitement Annotation processeur outil d'annotation).

    flowsheet

    • réalisation

    Ci-dessous, nous donnons pour illustrer la mise en uvre spécifique.

    Nous voulons appeler la méthode getVersion classe DnaVersion, d'abord tout ce que nous annoter.

    @DnaMethod public String getVersion { retourner android.os.Build.VERSION.RELEASE; }

    Ensuite, dans le DnaProcessor, l'ADN, le procédé de balayage de code AbstractProcessor par héritage, les méthodes annotées lecture DnaMethod: getVersion, et son procédé d'obtention d'informations, pour générer le proxy.

    Lors de la compilation, Dna nom du package similaire génère une classe proxy dans Dna_Class_Proxy DnaVersion, et où la génération du nom de la méthode proxy méthode proxy getVersion est le nom de la méthode de format de classe _. Ici, la génération de code JavaPoet est réalisé par les bibliothèques open source.

     @DnaParamFieldList ( params = {}, propriétaire = "me.ele.dna_example.DnaVersion", returnType = "java.lang.String" ) Object public static DnaVersion_getVersion (propriétaire DnaVersion) { retourner owner.getVersion; }

    Procédé automatiquement généré proxy getVersion

    Comme on peut le voir à partir de la méthode proxy, il appellera le corps entrant pour effectuer l'appel de méthode réelle. Remarques procédé proxy par DnaParamFieldList configuré avec trois paramètres. Pour le stockage params des paramètres liés à l'information, propriétaire pour stocker un nom de classe, returnType pour stocker des informations d'objet retourné.

    Lors de l'exécution, Dna trouverez fichier méthode DnaVersion_getVersion Dna_Class_Proxy par la réflexion, est déterminée par les paramètres DnaParamFieldList de savoir si cette méthode est l'objectif, puis de réaliser la méthode de réalisation getVersion d'exécution par la méthode proxy.

    Nous allons configurer des règles personnalisées pour éviter toute confusion classe proxy de confusion:

    . ** classe -Garder Dna_Class_Proxy {*;}

    Obscurcie fichier proxy:

    public class {Dna_Class_Proxy @a (a = {}, b = "me.ele.dna_example.DnaVersion") public static b Dna_Constructor_ProxyDnaVersion { retour nouveau b; } }

    On peut voir, Dna pas d'incidence sur la confusion du code d'origine, mais par des notes de classe proxy et les informations stockées, accédez à notre méthode cible. Afin d'obtenir la confusion dans le paquet de libération, appelez la méthode cible en fonction du nom de la méthode.

    Si vous voulez utiliser Dna, vous devez commenter le code natif DnaMethod, mais sous le code de Framework Android ne doit pas être confondu par défaut, mais ne peut pas être annotés. Cadre adn sous le code reflète les appels, plutôt que de prendre les appels de méthode proxy, de manière à obtenir un ajustement pour le code-cadre.

    les détails de mise en uvre iOS

    iOS obscurcissement inutile, riche par tous les appels d'interface de classe d'exécution de la méthode:

  • NSClassFromString obtenu en utilisant de l'objet de classe dynamique;

  • Utilisez NSSelectorFromString obtenir pour appeler le sélecteur de méthode;

  • Utilisation appel dynamique NSInvocation une méthode spécifique d'un objet, un tableau de paramètres variables sera jugé à son tour est basé sur le type d'objet sélecteur de codage non emballé, du type non-objet, la valeur de retour va tenter d'installer le paquet dans les types d'objet.

  • Le contexte du détail d'appel

  • Mettre en place objectsInContextMap, le stockage et la cartographie native entre tous objet réel object_id dans le JSON contexte.

  • Dans JSON ensemble invocationNodes contexte d'analyse syntaxique pour invocationNode est objet NSInvocation et appelle, seule valeur de retour cible d'appel NSInvocation sera convenu dans invocationNode object_id en objectsInContextMap, le prochain appel de l'appelant ou le paramètre peuvent provenir avant d'appeler la méthode objet résultant en une liaison Object_id pris dans le objectsInContextMap.

  • canal adn retourné comme la valeur de retour finale.

  • Merci pour regarder! Si elle est mauvaise, s'il vous plaît signaler! De plus, bienvenue Tucao!

    Adresse adn GitHub: https: //github.com/Assuner-Lee/dna suivi migreront vers le prochain compte élém.

    Lien original:

    https://lpdtech.blog.csdn.net/article/details/104651365

    2020 Examen d'entrée au collège prochain gros volumes de données, la visualisation des données vous indique comment remplir volontaire, choisir une école?
    Précédent
    Comic: a couru trois millions de fois les questions de vérification de code
    Prochain
    amis Tencent, clous et autres irrégularités sont des micro-canal appel public, Google met à jour des millions de vulnérabilités Android de réparation de puce, Microsoft .NET terminée support pour bas
    Les fabricants nationaux et étrangers construire, Télétravail carte de rapport d'examen final publié
    Chunmian ne s'en est pas rendu compte, que savez-vous de SQL ? | Le projet Force
    Ali exclusive secret de vol plateforme de recherche Roselle système d'exploitation comment soutenir 268400000000 pro mondiale! | Interrogé à la fin de l'évolution des technologies de l'information de
    Java 11 mise à jour: "la dette", "crise"
    Un à comprendre ElasticSearch | programme de travail
    Milliards d'équipements Wi-Fi est défectueuse, les communications écoute clandestine
    Google et Microsoft dans la guerre des navigateurs
    Linux deviendra le système d'exploitation de bureau grand public?
    « Pas prendre » l'équipe médicale! Guangdong Hôpital de Jingzhou service Internet plus de deux mille passagers par jour
    Guangzhou, a déclaré une école de conduite, mais lose 5000 stagiaires n'ont pas testé avaient également proposer d'obtenir une indemnisation à payer 3000
    A part d'emballement: la chasse aux stocks de haute consommation, vous avez vraiment le mien à la maison?