Flutter和原生交互學習


 

PlatformChannel功能簡介

PlatformChannel分為BasicMessageChannel、MethodChannel以及EventChannel三種。其各自的主要用途如下:

  • BasicMessageChannel: 用於傳遞數據。Flutter與原生項目的資源是不共享的,可以通過BasicMessageChannel來獲取Native項目的圖標等資源。
  • MethodChannel: 傳遞方法調用。Flutter主動調用Native的方法,並獲取相應的返回值。比如獲取系統電量,發起Toast等調用系統API,可以通過這個來完成。
  • EventChannel: 傳遞事件。這里是Native將事件通知到Flutter。比如Flutter需要監聽網絡情況,這時候MethodChannel就無法勝任這個需求了。EventChannel可以將Flutter的一個監聽交給Native,Native去做網絡廣播的監聽,當收到廣播后借助EventChannel調用Flutter注冊的監聽,完成對Flutter的事件通知。

其實可以看到,無論傳方法還是傳事件,其本質上都是數據的傳遞,不過上層包的一些邏輯不同而已。

 

flutter

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class ChannelPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new _ChannelPageState();
  }
}

class _ChannelPageState extends State<ChannelPage> {

  //獲取到插件與原生的交互通道
  static const jumpPlugin = const MethodChannel('com.example.jump/plugin');
  static const counterPlugin = const EventChannel('com.example.counter/plugin');
  var _count;
  StreamSubscription _counterSub;
  @override
  void initState() {
    super.initState();
    _startCounterPlugin();
  }

  @override
  void dispose() {
    super.dispose();
    _endCounterPlugin();
  }
  void _startCounterPlugin(){
    if(_counterSub == null){
      _counterSub =  counterPlugin.receiveBroadcastStream().listen(_onCounterEvent,onError: _onCounterError);
    }
  }

  void _endCounterPlugin(){
    if(_counterSub != null){
      _counterSub.cancel();
    }
  }
  void _onCounterError(Object error) {
    setState(() {
      _count = "計時器異常";
      print(error);
    });
  }

  void _onCounterEvent(Object event) {
    setState(() {
      _count = event;
    });
  }


  Future<Null> _jumpToNative() async {
    String result = await jumpPlugin.invokeMethod('oneAct');

    print(result);
  }

  Future<Null> _jumpToNativeWithValue() async {

    Map<String, String> map = { "flutter": "這是一條來自flutter的參數" };

    String result = await jumpPlugin.invokeMethod('twoAct', map);

    print(result);
  }


  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Channel"),
        centerTitle: true,
      ),
      body: new Center(
          child: new ListView(
            children: <Widget>[
              new Padding(
                padding: const EdgeInsets.only(left: 10.0, top: 10.0, right: 10.0),
                child: new RaisedButton(
                    textColor: Colors.black,
                    child: new Text('跳轉到原生界面'),
                    onPressed: () {
                      _jumpToNative();
                    }),
              ),
              new Padding(
                padding: const EdgeInsets.only(
                    left: 10.0, top: 10.0, right: 10.0),
                child: new RaisedButton(
                    textColor: Colors.black,
                    child: new Text('跳轉到原生界面(帶參數)'),
                    onPressed: () {
                      _jumpToNativeWithValue();
                    }),
              ),

              new Padding(
                padding: const EdgeInsets.only(
                    left: 10.0, top: 10.0, right: 10.0),
                child: new Text('這是一個從原生發射過來的數據:$_count'),
              ),


            ],
          )
      ),
    );
  }
}

android

package com.example.flutter_app.plugins;

import android.app.Activity;
import android.util.Log;


import io.flutter.plugin.common.EventChannel;
import io.flutter.plugin.common.PluginRegistry;


public class FlutterPluginCounter implements EventChannel.StreamHandler {

    public static String CHANNEL = "com.example.counter/plugin";

    static EventChannel channel;

    private Activity activity;


    private FlutterPluginCounter(Activity activity) {
        this.activity = activity;
    }

    public static void registerWith(PluginRegistry.Registrar registrar) {
        channel = new EventChannel(registrar.messenger(), CHANNEL);
        FlutterPluginCounter instance = new FlutterPluginCounter(registrar.activity());
        channel.setStreamHandler(instance);
       // basicMessageChannel = new BasicMessageChannel<String> ("foo", StringCodec.INSTANCE);
    }

    @Override
    public void onListen(Object o, final EventChannel.EventSink eventSink) {
        eventSink.success(123456);
    }

    @Override
    public void onCancel(Object o) {
        Log.i("FlutterPluginCounter", "FlutterPluginCounter:onCancel");
    }

}
package com.example.flutter_app.plugins;

import android.app.Activity;
import android.content.Intent;


import com.example.flutter_app.OneActivity;
import com.example.flutter_app.TwoActivity;

import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.PluginRegistry;

public class FlutterPluginJumpToAct implements MethodCallHandler {

    public static String CHANNEL = "com.example.jump/plugin";

    static MethodChannel channel;

    private Activity activity;

    private FlutterPluginJumpToAct(Activity activity) {
        this.activity = activity;
    }

    public static void registerWith(PluginRegistry.Registrar registrar) {
        channel = new MethodChannel(registrar.messenger(), CHANNEL);
        FlutterPluginJumpToAct instance = new FlutterPluginJumpToAct(registrar.activity());
        //setMethodCallHandler在此通道上接收方法調用的回調
        channel.setMethodCallHandler(instance);
    }

    @Override
    public void onMethodCall(MethodCall call, MethodChannel.Result result) {

        //通過MethodCall可以獲取參數和方法名,然后再尋找對應的平台業務,本案例做了2個跳轉的業務

        //接收來自flutter的指令oneAct
        if (call.method.equals("oneAct")) {

            //跳轉到指定Activity
            Intent intent = new Intent(activity, OneActivity.class);
            activity.startActivity(intent);

            //返回給flutter的參數
            result.success("success");
        }
        //接收來自flutter的指令twoAct
        else if (call.method.equals("twoAct")) {

            //解析參數
            String text = call.argument("flutter");

            //帶參數跳轉到指定Activity
            Intent intent = new Intent(activity, TwoActivity.class);
            intent.putExtra(TwoActivity.VALUE, text);
            activity.startActivity(intent);

            //返回給flutter的參數
            result.success("success");
        }
        else {
            result.notImplemented();
        }
    }

}
package com.example.flutter_app;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class OneActivity extends Activity implements View.OnClickListener {

    private Button mGoFlutterBtn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_one);

        mGoFlutterBtn = findViewById(R.id.go_flutter);

        mGoFlutterBtn.setOnClickListener(this);

    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.go_flutter:
                Intent intent = new Intent(this, MainActivity.class);
                startActivity(intent);
                break;
        }
    }

}
package com.example.flutter_app;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class TwoActivity extends Activity{

    private TextView mTextView;

    public static final String VALUE = "value";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_two);

        mTextView = findViewById(R.id.text);

        String text = getIntent().getStringExtra(VALUE);

        mTextView.setText(text);

    }

}
package com.example.flutter_app;

import android.os.Bundle;

import com.example.flutter_app.plugins.FlutterPluginCounter;
import com.example.flutter_app.plugins.FlutterPluginJumpToAct;

import io.flutter.app.FlutterActivity;
import io.flutter.plugins.GeneratedPluginRegistrant;

public class MainActivity extends FlutterActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    FlutterPluginJumpToAct.registerWith(this.registrarFor(FlutterPluginJumpToAct.CHANNEL));//注冊
    FlutterPluginCounter.registerWith(this.registrarFor(FlutterPluginCounter.CHANNEL));//注冊

  }
}

activity_one.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/go_flutter"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="去Flutter界面"></Button>
</LinearLayout>

activity_two.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
</LinearLayout>

 

效果:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM