I remember learning about flutter when it first came out. However, because of the complex composition of flutter and the lack of a stable version, he gave up on further study at that time. Now, with the development of flutter and the push of the big players, he started to fall into the trap of flutter.

Although The Flutter can be developed cross-platform, it is not possible to re-develop the flutter because most of the projects are already existing, so it is mostly a mixed development solution of Native + Flutter. So how does this scheme work?

1. Import of flutter module

First, switch to a directory one level above the root of the Native project. Take the author project as an example, the path is D:\FlutterHybrid\FlutterHybridAndroid, and then through the command CD.. / Switch to the upper directory. Execute the following command to create a Flutter module.

    flutter create -t module flutter_module
Copy the code

The flutter_module above is the name of the flutter module we created.

Once the Flutter module has been created, we need to import the module through the following steps.

  1. In the first place in thesettings.gradleAdd the following code to the file.
        setBinding(new Binding([gradle:this]))
        evaluate(new File(
                settingsDir.parentFile,'flutter_module/.android/include_flutter.groovy'
        ))
    Copy the code

    Once added, the Flutter module will be visible in Android Studio, as shown below.

  2. Second, after the Flutter module is displayed correctly, we need to passimplementation project(':flutter')To import the module. When you start compiling the project after the addition is successful, you may encounter the following error.

    So that’s one of the things we need to be aware of,A native of the projectminSdkVersionNot less than the Flutter moduleminSdkVersion. The solution is to takeA native of the projectminSdkVersionTo be greater than the value of the Flutter moduleminSdkVersionThe value of the.

After the above two steps, the Native project has successfully imported the Flutter module and is ready to run the Native project. However, the following errors can occur when running a Native project.

app
build.gradle

    android {
        compileOptions {
            sourceCompatibility 1.8
            targetCompatibility 1.8}}Copy the code

Then proceed with the Native project and you will be able to run on the device, but how do you verify that the Flutter module is packaged into the APK lini? This is where Android Studio’s APK analytics tool comes in. Using this tool, you can see that the APK package consists of the following.

flutter_assets

Note: using AndroidX in a project can cause serious compatibility issues. So if your project is using AndroidX, import the Flutter module with caution. If you must import, read the Official Solution offered by Flutter – AndroidX Compatibility.

2. Native project loads the Flutter page

After a few steps, we have successfully relied on the Flutter module in our Native project, so let’s learn how to load the Flutter page in our Native project. Looking at the Code of the Flutter module, you can see that the module provides the following two ways to load the Flutter page.

  1. Build the Flutter page into a View and display the flutter page through addView
  2. Build the flutter page into a Fragment, and display the flutter page by manipulating the Fragment

2.1. Build the Flutter page into a View

The Flutter class of the Flutter module gives us a method called createView. In this way, we can build the Flutter page into a View. The operation of the View is familiar to any Android developer, so I added the Flutter page to the appropriate place via addView. The implementation code is as follows:

    public void onLoadFlutter(View view) {
        View flutterView = Flutter.createView(this, getLifecycle(), "route1");
        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(600.600);
        layoutParams.topMargin = 100;
        addContentView(flutterView, layoutParams);
    }
Copy the code

2.2. Build the Flutter page into fragments

Also, the flutter module provides a method — createFragment — to build the flutter page into a fragment and then add the flutter page to the corresponding place according to the fragment. The implementation code is as follows:

    public void onLoadFlutter(View view) {
       FragmentTransaction transaction= getSupportFragmentManager().beginTransaction();
       transaction.replace(R.id.someContainer,Flutter.createFragment("Here's the Flutter page."));
       transaction.commit();
    }
Copy the code

2.3. Flutter page

Having explained how to load the Flutter page in a Native project, let’s take a look at the code for the Flutter page. The code is also very simple, the basic code is automatically generated when creating a module.

import 'package:flutter/material.dart';
import 'dart:ui';

void main() => runApp(MyApp(
      initParams: window.defaultRouteName,
    ));

class MyApp extends StatelessWidget {
  final String initParams;

  MyApp({Key key, @required this.initParams}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(
        title: 'Flutter Demo Home Page', initParams: initParams, ), ); }}class MyHomePage extends StatefulWidget {
  final String initParams;

  MyHomePage({Key key, this.title, this.initParams}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState(initParams);
}

class _MyHomePageState extends State<MyHomePage> {
  final String initParams;

  _MyHomePageState(this.initParams);

  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'initParams:$initParams',
              style: TextStyle(color: Colors.red),
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment', child: Icon(Icons.add), ), ); }}Copy the code

As you can see, in the above code, we’re passing in an initialization property, which is actually a route name, but we’re also passing in a JSON or some other type of data to do something else. This can be seen as a communication between Native and Flutter.

3. Debugging of flutter module

3.1 Hot overload of the FLUTTER module

One of the advantages of Flutter is that it can be quickly debugged during development by hot overloading. However, running the above code shows that the modification of the Flutter module code does not take effect immediately and requires repackaging Native to take effect. This negates one of the major advantages of the Flutter and reduces debugging efficiency. So can we do a hot load of the Flutter module in the hybrid project? You can do that, but you have to go through some steps.

  1. First, close the current application. Note: kill the process in which the current application is running, not exit the application.

  2. Next, entering the command flutter attach in the Flutter module displays the following.

  3. Finally, open the app again and you’ll see something like this.

    Please pay attention to the passage in the picture

    🔥 To hot reload changes while running, press “r”. To hot restart (and rebuild state), press “R”.

    It tells us to press R if we want a hot reload, or to press R if we want a hot reboot. When you have modified the Flutter code, press the R key and the following message will appear indicating that the modification was successful.

By following the steps above, we were able to use the hot overload feature of the Flutter in a mixed project, with the modification of the flutter taking effect immediately.

3.2 Debugging of flutter module

The only difference between the hybrid project’s Flutter module debugging and the Project’s flutter module debugging is how to set up sockets between Android Studio and devices. In the Flutter project, we can simply click the Debug button to debug, but in the mixed project, this button will not work and the connection will have to be established in some other way. Android Studio provides us with the Flutter Attach button, which allows us to connect the module to the device and debug the module.

4, summarize

With the above explanation, it is possible to use the hybrid development of Native + Flutter. However, if you look carefully, the Flutter module does not communicate with the Native project in the previous presentation, so how should it communicate? This article describes the communication between Android and Flutter in detail.