Flutter from entry to abandonment

background

From setup to project development, Flutter has been in the pit for almost a week. I have to say, from an Android native developer’s perspective, Flutter is relatively friendly compared to other cross-platform solutions in terms of performance, UI rendering and learning costs. It maintains several sets of UI logic internally, skia engine rendering, But understand that Flutter is always a cross-platform UI solution and ultimately generates.apk(Android)/.ipa(ios) packages based on the platform. Therefore, when it comes to some system platform interfaces or data, For example, the system electricity needs to be handled by the Native layer, and then the data is returned to the flutter layer for display. Therefore, it is inevitable that there will be communication problems between the flutter and the native layer. Then, how does the flutter achieve this? Platform Channels

Platform Channels

The diagram above from the Website of Flutter shows the architecture of Platform Channels. Don’t you say that Flutter and Native communicate through Platform Channels? How come the schema connects them with a MethodChannel? Actually, MethodChannel is a type of Platform Channels, and as the name implies, MethodChannel should be used much like a method call. So there are other channels? Yes, there are EventChannel, BasicMessageChannel, etc. If you need to send data from Native to Flutter, EventChannel is recommended. The Flutter framework also uses these channels to communicate with Native

Example 1: Flutter calls Android logcat

Although Flutter itself provides two log output methods: print() and debugprint(), it is not very comfortable for Android developers. Information is redundant in the console bar and cannot be filtered, etc. So you can call android native Logcat through Channels

The Flutter end
import 'package:flutter/services.dart';

class LogUtils {
  static const perform = const MethodChannel("android_log");

  static void v(String tag, String message) {
    perform.invokeMethod('logV', {'tag': tag, 'msg': message});
  }

  static void d(String tag, String message) {
    perform.invokeMethod('logD', {'tag': tag, 'msg': message});
  }

  static void i(String tag, String message) {
    perform.invokeMethod('logI', {'tag': tag, 'msg': message});
  }

  static void w(String tag, String message) {
    perform.invokeMethod('logW', {'tag': tag, 'msg': message});
  }

  static void e(String tag, String message) {
    perform.invokeMethod('logE', {'tag': tag, 'msg': message}); }}Copy the code

As you can see, the code is simple: initialize a MethodChannel object and then call the invokeMethod method, passing in the parameters

The android end
public class MainActivity extends FlutterActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        GeneratedPluginRegistrant.registerWith(this);
        new MethodChannel(getFlutterView(),CHANNEL).setMethodCallHandler(new MethodChannel.MethodCallHandler() {
            @Override
            public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
                String tag = methodCall.argument("tag");
                String msg = methodCall.argument("msg");
                switch (methodCall.method) {
                    case "logV":
                        Log.v(tag,msg);
                        break;
                    case "logD":
                        Log.d(tag,msg);
                        break;
                    case "logI":
                        Log.i(tag,msg);
                        break;
                    case "logW":
                        Log.w(tag,msg);
                        break;
                    case "logE":
                        Log.e(tag,msg);
                        break;
                    default:
                        Log.d(tag,msg);
                        break; }}}); }Copy the code

MethodCallHandler (); method (); arguments (); log ();

Example 2: Android pushes messages to Flutter

Because most of the current flutter and native development, many flutter needs to actively push messages to the native layer. The native layer can create an EventChannel to monitor the status of flutter and then reply the message OBJ through the EventSink object

The android end
new EventChannel(getFlutterView(), "com.flutter/notify").setStreamHandler(
                new EventChannel.StreamHandler() {
                    private TokenReceiver tokenReceiver;
                    @Override
                    public void onListen(Object args, final EventChannel.EventSink events) {
                        Log.e("tag"."adding listener");
                        events.success("data callback");
                    }

                    @Override
                    public void onCancel(Object args) {
                        Log.e("tag"."cancelling listener"); }});Copy the code
flutter
static const EventChannel eventChannel = EventChannel('com.flutter/notify');
@override
  void initState() {
    // TODO: implement initState
    super.initState();
    // Initialize the listener
   eventChannel.receiveBroadcastStream().listen(_onDataBack, onError: _onError);
  }
void _onError(Object error){

  }
void _onDataBack(String callback) {
   print(callback)
  }
Copy the code

Create an EventChannel with the same Channel name and listen for the data to do the corresponding logic