(Original) Die Art und Weise, wie Flutter mit Native kommuniziert: MethodChannel

Vorwort

Da immer mehr Flutter-Hybrid-Entwicklungsprojekte entwickelt werden, haben wir auch ein praktisches Szenario,
nämlich die Art und Weise, wie Flutter mit der nativen Seite kommuniziert.
Derzeit scheint es ungefähr drei Möglichkeiten zu geben, nämlich: MethodChannel .MessageChannel
EventChannel . Um jedoch allen den Unterschied zwischen den drei klarer zu machen, wurde dieser Blog erstellt. In diesem Artikel geht es hauptsächlich um die MethodChannel-Methode , die auch die am häufigsten verwendete Methode ist in der tatsächlichen Entwicklung. Für die anderen beiden Methoden können Sie den nächsten Blog lesen: EventChannel und BasicMessageChannel , also fangen wir jetzt offiziell an








erreichen

FlutterActivity

Zunächst müssen wir wissen, dass die sogenannten Seiten von Flutter letztendlich tatsächlich auf Aktivität laufen.
Dies ist ein bisschen wie unser WebView. Was letztendlich die Seite hostet, ist immer noch eine Aktivität.
In Flutter, was die Seite hostet ist eigentlich eine Aktivität namens FlutterActivity-Klasse.
Unsere Interaktion ist also eigentlich die Interaktion zwischen Flutter Page und dieser FlutterActivity.
Zuerst erstellen wir eine neue gewöhnliche Aktivität, die die Startseite ist.

class MainActivity : AppCompatActivity() {
    
    


  override fun onCreate(savedInstanceState: Bundle?) {
    
    
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    findViewById<TextView>(R.id.textview).setOnClickListener {
    
    
      startActivity(MyFlutterActivity.withCachedEngine("your_engine_id").build(this))
    }
  }

}

Diese Homepage ist unsere grundlegendste AppCompatActivity,
sie steht nicht im Mittelpunkt.
Klicken Sie auf die Schaltfläche, um die von uns gehostete Seite Flutter aufzurufen: MyFlutterActivity
, die eine Klasse namens FlutterFragmentActivity erbt.
Diese Seite kann offiziell auf einer eigenen Seite mit der Flutter-Seite interagieren.
Der entsprechende Interaktionscode wird auch hier geschrieben.

Die Flutter-Seite ruft die Android-Seite auf

Schauen wir uns zunächst an, wie wir es auf der Flutter-Seite implementieren.
Zuerst können wir eine neue Datei ForNativePlugin.dart erstellen.
Diese Datei wird verwendet, um die Methode zu definieren, die auf der Android-Seite aufgerufen werden soll.

class ForNativePlugin {
    
    
  MethodChannel methodChannel = const MethodChannel("ForNativePlugin");

  /// 调用安卓,得到当前时间
  Future<String> getTime() async {
    
    
    var nowTime = await methodChannel.invokeMethod("getTime");
    return nowTime;
  }


  /// 显示安卓土司
  showAndroidToast(String msg) async {
    
    
    try {
    
    
      await methodChannel.invokeMethod('toast', {
    
    'msg': msg});
    } on PlatformException catch (e) {
    
    
      print(e.toString());
    }
  }
}

Wie Sie sehen, wird eine MethodChannel-Klasse erstellt.
Dies ist die Schlüsselklasse für die Interaktion.
Das Namensattribut von MethodChannel muss für die beidseitige Entwicklung vereinbart werden.
Hier wird ein ForNativePlugin-String vereinbart.
Anschließend werden zwei Methoden definiert
. Die Die Implementierung der Methode besteht eigentlich darin, methodChanneld.invokeMethod zu verwenden. Um die Methode invokeMethod auf der Android-Seite auszulösen
, schreiben Sie den Methodennamen auf der Android-Seite als einen Parameter und den Namen des Parameters auf den zweiten Parameter. Es können mehrere sein Eingabeparameter.

Nach dem Schreiben können wir diese Klasse in Flutter erstellen

ForNativePlugin forNativePlugin = ForNativePlugin();

Verwenden Sie dann die von uns geschriebene Toolklasse, um bei Bedarf die Methoden auf der Android-Seite auszulösen.
Zum Beispiel:

forNativePlugin.showAndroidToast("当前时间为:${
      
      forNativePlugin.getTime()}");

Auf diese Weise können wir die Android-Seite aufrufen, um die Uhrzeit abzurufen, und uns dann von der Android-Seite helfen lassen, die Uhrzeit zurückzugeben und
sie über die Toast-Methode anzuzeigen
. Wie schreibt man also die Android-Seite?
Es ist auch sehr einfach: Auf der Android-Seite muss außerdem eine Klasse definiert werden,
um die onMethodCall-Methode der MethodCallHandler-Schnittstelle zu implementieren.

class MyMethodCallHandler(var context: Context) : MethodCallHandler {
    
    
  override fun onMethodCall(methodCall: MethodCall, result: MethodChannel.Result) {
    
    
    when (methodCall.method) {
    
    
      "getTime" -> {
    
    
        result.success(SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(System.currentTimeMillis()))
      }
      "toast" -> {
    
    
        if (methodCall.hasArgument("msg") && !TextUtils.isEmpty(
            methodCall.argument<Any>("msg").toString()
          )
        ) {
    
    
          Toast.makeText(context, methodCall.argument<Any>("msg").toString(), Toast.LENGTH_LONG)
            .show()
        } else {
    
    
//          result.error()
          Toast.makeText(context, "msg 不能为空", Toast.LENGTH_SHORT).show()
        }
      }
      else -> {
    
    
        // 表明没有对应实现
        result.notImplemented()
      }
    }
  }
}

Die onMethodCall-Methode wird verwendet, um die Logik zu verarbeiten, die ausgelöst werden soll.
Dann kommen wir zu der Klasse, die FlutterFragmentActivity erbt.
Zuerst definieren wir auch einen MethodChannel.

private lateinit var flutterMethodChannel: MethodChannel

Lassen Sie dann unsere Aktivität die Methode configureFlutterEngine implementieren

  override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
    
    
    super.configureFlutterEngine(flutterEngine)
    //通过MethodChannel与原生通信,ForNativePlugin为约定字段
    flutterMethodChannel = MethodChannel(flutterEngine.dartExecutor, "ForNativePlugin")
    flutterMethodChannel.setMethodCallHandler(MyMethodCallHandler(this))
  }

Wie Sie sehen können, handelt es sich tatsächlich um einen Registrierungslink.
Registrieren Sie unsere MyMethodCallHandler-Klasse in MethodChannel
. An diesem Punkt ruft die Flutter-Seite den Android-Seitencode auf.

Ein zusätzlicher Punkt:
Wenn die Android-Seite ausgelöst wird,
können Sie Flutter über die Ergebnisklasse mitteilen, ob das Anforderungsergebnis erfolgreich ist oder nicht.
result.success(), success,
result.error(), failed
, result.notImplemented(). Für diese Methode gibt es keine entsprechende Implementierung.

Die Android-Seite ruft die Flutter-Seite auf

Der Aufruf der Flutter-Seite auf der Android-Seite ist tatsächlich ähnlich.
Zuerst die Android-Seite:
Wir können eine FlutterEngine erhalten, indem wir die getFlutterEngine-Methode aufrufen
und dann den getDartExecutor dieser FlutterEngine zum Betrieb verwenden.

  fun toFlutter(num1: Int, num2: Int) {
    
    
    flutterEngine?.dartExecutor?.let {
    
    
      nativeMethodChannel = MethodChannel(it, "ForFlutterPlugin")
      nativeMethodChannel.invokeMethod(
        "callFlutterSum",
        listOf<Int>(num1, num2),
        object : MethodChannel.Result {
    
    
          override fun success(result: Any?) {
    
    
            Log.d("MyFlutterActivity", "计算结果为 = $result")
          }

          override fun error(errorCode: String, errorMessage: String?, errorDetails: Any?) {
    
    
            Log.d("MyFlutterActivity", "出错了:$errorCode, $errorMessage, $errorDetails")
          }

          override fun notImplemented() {
    
    
            Log.d("MyFlutterActivity", "notImplemented")
          }
        })
    }
  }

Wie Sie hier sehen können, ist auch ein MethodChannel definiert. Das vereinbarte Feld lautet: ForFlutterPlugin
und ruft dann die Methode callFlutterSum auf der Flutter-Seite auf, um den berechneten Rückgabewert zu erhalten.
Hierbei ist zu beachten, dass der aufrufende Fluter-Code im sein muss Haupt-Bedroung.

Kommen Sie dann zur Flutter-Seite
und definieren Sie den MethodChannel auf der Flutter-Seite:

MethodChannel methodChannel = const MethodChannel("ForFlutterPlugin");

Und um die Registrierung und Rückrufüberwachung durchzuführen, können Sie sich in der initState-Methode registrieren:

  
  void initState() {
    
    
    // TODO: implement initState
    super.initState();
    methodChannel.setMethodCallHandler(
      (call) {
    
    
        switch (call.method) {
    
    
          case 'callFlutterSum':
            print('call callMe : arguments = ${
      
      call.arguments}');
            List<Object?> numbers = call.arguments;
            var num1=numbers[0] as int;
            var num2=numbers[1] as int;
            //触发Android端的success方法
            return Future.value(num1+num2);
            //触发Android端的error方法,errorCode为error,errorMessage为:调用出错,不能传details
            // return Future.error("调用出错");
            //触发Android端的error方法,可以额外传details对象
            throw PlatformException(code: 'errorCode', message: 'Error occurred',details: "出错了");
          default:
            print('Unknowm method ${
      
      call.method}');
            //触发Android端的notImplemented方法
            throw MissingPluginException();
        }
      },
    );
  }

Zu diesem Zeitpunkt ist die Arbeit auf der Flutter-Seite abgeschlossen
. Es ist ersichtlich, dass die gegenseitigen Aufrufe zwischen den beiden Enden grundsätzlich in drei Schritte unterteilt sind:
1: Die aufgerufene Seite schreibt zuerst die aufgerufene Verarbeitungslogik
2: Die aufgerufene Seite erstellt den MethodChannel und ruft setMethodCallHandler auf, um sich zu registrieren.
3: Die aufrufende Seite erstellt einen MethodChannel, stimmt den Feldern zu und verwendet dann invokeMethod, um die Methode aktiv aufzurufen.

Beachten

Wenn Sie beim Schreiben einer doppelseitigen Kommunikation feststellen, dass der Aufruf nicht ausgelöst wird, können Sie auf die folgenden Gründe achten:
1: Ob FlutterFragmentActivity oder FlutterActivity geerbt wird
2: Ob die vereinbarten Felder konsistent sind
3: Ob der Methodenname und Parameter sind konsistent

Quellcode

Quellcode-Adresse dieses Blogs:
MethodChannel

Relevante Information

Dies ist eine umfassende und detaillierte Studienanleitung zu den Kommunikationsmethoden zwischen Android Native und Flutter.

Acho que você gosta

Origin blog.csdn.net/Android_xiong_st/article/details/131904836
Recomendado
Clasificación