As a loyal and more experienced Android fan, HE recently took some time out to study Google’s own son, Flutter, which is still a bit of a footnote.

Since Google first proposed Flutter in 2017 and Beta in 2018, coupled with various disturbances and problems of RN, Flutter has become increasingly popular. Many domestic companies have announced the application of Flutter in their products, such as Meituan and Xianyu.

preface

Flutter, as a cross-platform framework, is often compared to React Native and Xamarin. The principle of Flutter is very different from both of them, except that everyone is a cross-platform framework and can achieve an almost Native experience.

Let’s take a look at the diagram of all three.

It might be a little complicated, but let’s explain it.

React Native and Xamarin are both frameworks to realize the so-called Native experience based on mapping Native code, but RN deals with Native based on JS engine + Bridge, and binds it at runtime. Xamarin is based on Microsoft’s linux-based C# virtual machine mono + JNI to communicate with native.

There is still a difference between Android and iOS. For example, THE JS engine of RN on iOS does not support JIT, which will affect efficiency to a certain extent. Xamarin on iOS can be directly compiled into programs that can be executed on iOS platform, so the performance in actual operation is the same. The only difference is that Microsoft supports API synchronization faster.

For Flutter, its rendering engine uses Skia direct drawing, plus the C++ based Dart engine, so there is no difference between platforms. Plus, it has both Android Material Design and iOS Cupertino UI components. So even a self-painted component will look exactly the same as the native one.

Based on the general understanding of the three cross-platform engines, we can see that they have reached a certain degree of Native experience, but each has certain performance loss, such as the loading OF JS by RN’s JS engine, the loss of Bridge communication, and the loss of communication between Xamarin Mono VIRTUAL machine and Java. And the differences between Flutter Skia rendering and Native Android rendering.

Flutter notes

How do I start an app

Android needs to specify an Activity declaration with the MAIN Action and LAUNCHER category in Manfest, whereas Flutter requires only one line.

void main() => runApp(MyApp());Copy the code

MyApp is a normal Widgets(View).

View vs Widgets

Flutter does not have a View. Instead, it has widgets, which are divided into StatelessWidgets and StatefulWidgets. The former is a static View, while the latter is a View that is dynamically updated with Data.

  • Stateless
Text( 'I like Flutter! ', a);Copy the code
  • Stateful
class StatefulText extends StatefulWidget { @override State<StatefulWidget> createState() => _TextState(); } class _TextState extends State<StatefulText> { // Default placeholder text String textToShow = "I Like Flutter"; void _updateText() { setState(() { // update the text textToShow = "Flutter is Awesome!" ; }); } @override Widget build(BuildContext context) { ... invoke _updateText } }Copy the code

This is actually because StatefulWidgets trigger a redraw of the entire widget tree by calling State’s setState method, and the passed (){… }block.

How to write Layout, where the XML went.

Flutter actually has no XML and implements a layout through the nesting of Widgets.

Such as:

  • CenterIs a container in which you can put child Views in the center.
  • RowThe corresponding LinearLayout + Horizontal,ColumnThe corresponding is LinearLayout + Vertical, and they both have a property called LinearLayoutcrossAxisAlignmentSomething like thatgravityTo control the position of the child View relative to the parent View.
  • ExpandedSupports a weight like attribute calledflex.
  • ContainerIs a person withdecorationProperty, which can be used to control background color, border, margin, etc.
  • StackKind of like a special RelatetiveLayout or ConstraintLayout,childrenProperty specifies its child views, the first being the Base View,alignmentProperty specifies the position of the subsequent child View relative to the BaseView, as inAlignment: const alignment (0.6, 0.6)Specifies the location in the lower right corner of the BaseView.
  • ListTileIs a special ListItem with three attributes: Icon (leading) on the left, title (title), and Icon (trailing) on the right.
  • There are such asListView.GridView.CardAnd more familiar Widgets.

There is another widget similar to our Activity:

  • calledMaterialApp, you can specifytheme.title, and subviewshomeThere are even more important page jumpsroutes.
MaterialApp( title: 'Welcome to Flutter', home: ... , routes: <String, WidgetBuilder> ... , theme: ThemeData( primaryColor: Colors.white ), )Copy the code

There is also a Fragment similar to:

  • calledScaffoldIn Chinese, it meansThe scaffoldIt contains an appBar (ActionBar) and a body, and the appBar can specify title and Actions (similar to action button click events).
Scaffold( appBar: AppBar( title: Text(widget.title), actions: <Widget>[...] , ), body: ... .)Copy the code

How do I Remove an element from a parent View

The answer is no… This is because the structure of the tree of a Flutter cannot be changed. However, if a Flutter is changed, the Data can be redrawn using the setState method of StatefulWidgets, thus replacing the previous Widgets.

What about those of you who like to draw Canvas?

Flutter also supports this function. CustomPaint, as a widget, can pass in a parameter that implements the CustomPainter abstract class. The CustomPainter abstract method is similar to onDraw of Android View.

void paint(Canvas canvas, Size size)

bool shouldRepaint(CustomPainter oldDelegate)Copy the code

How do I customize a View

In my view, instead of heredity, we will be using an Android ViewGroup approach of composing and encapsulating small Widgets into new Widgets that are needed.

Where does one of the four components of the Intent go

MaterialApp is an Activity like MaterialApp.

Use Navigator and Routes to jump to the interface, which is actually the replacement of the entire Widgets.

routes: <String, WidgetBuilder> {
      '/a': (BuildContext context) => MyPage(title: 'page A'),
      '/b': (BuildContext context) => MyPage(title: 'page B'),
      '/c': (BuildContext context) => MyPage(title: 'page C'),
    }
    
Navigator.of(context).pushNamed('/b');Copy the code

How do I handle external IntEnts

You actually need to register the filter in the Android shell of the Flutter App and save it in the FlutterActivity.

After initializing the FlutterView, the Bridge (officially called MethodChannel) gets the FlutterView from Java for the next logical step.

Let’s look at a simple example.

new MethodChannel(getFlutterView(), "app.channel.shared.data").setMethodCallHandler( new MethodCallHandler() { @Override public void onMethodCall(MethodCall  call, MethodChannel.Result result) { if (call.method.contentEquals("getSharedText")) { result.success(sharedText); sharedText = null; }}}); getSharedText() async { var sharedData = await platform.invokeMethod("getSharedText"); if (sharedData ! = null) { setState(() { dataShared = sharedData; }); }}Copy the code

What about startActivityForResult?

This Flutter has the exact corresponding method and is very convenient to use, combined with the page jump mentioned earlier:

Map xxx = await Navigator.of(context).pushNamed('/xxx');


Navigator.of(context).pop({xxx});
Copy the code

What about asynchrony, where is runOnUiThread()

Flutter is a bit like JS. It is a single-threaded mode, so it only builds simple async by emulation. Keywords are processed with await+async just like Kotlin Coroutines.

Such as:

loadData() async {
    response = await http.get(xxx);
    setState(() {xxx});
}Copy the code

However, because of its single thread, it cannot do long blocking operations, such as HTTP request latency is normally milliseconds, but data processing, etc., may be seconds.

This is also one of RN’s pain points when it comes to threads for Android applications. Flutter uses an easy-to-think curve to save the country. It provides an object called Isolate, which is actually a socket-based data channel that processes data in an independent process. It then sends back to the application process through the socket. Remember the pipe of interprocess communication?

For details on the API, see documentation 1… , 2, 3,…

Flutter replaces OkHttp’s web library

Come with HTTP library, direct HTTP.get (URL), in the thread part of the code example is also involved.

Introduced via the gradle-like file pubspec.yaml.

dependencies: ... HTTP: ^ 0.12Copy the code

^ Indicates that you do not upgrade the gradle version and take the latest version, which is smaller than gradle +.

Loading Content Error LCE(Loading Content Error

Flutter has a widget called the ProgressIndicator. For example, we expect the Loading screen to turn in a loop before data is loaded.

We can through StatefulWidgets, according to the data, or List the number of Widgets (if it is displayed a List) to determine whether to display Loading, use a subclass CircularProgressIndicator, To replace the page Widgets.

SetState (() {… }) to trigger an interface refresh, which can trigger asynchronous loading of data within initState().

How to put different resolution picture resources

This is a little bit like iOS, which is 1x,2x,3x:

Images /my_icon. PNG // Base: 1.0x image images/2.0x/my_icon. PNG // 2.0x image images/3.0x/my_icon. PNG // 3.0x imageCopy the code

The difference also needs to be added to the gradle-like file pubspec.yaml.

assets:
 - images/my_icon.jpegCopy the code

How to store strings

Flutter doesn’t have anything like Android string.xml. For now, it’s best to store Flutter as a static string.

class Strings {
  static String welcomeMessage = "Welcome To Flutter";
}

Text(Strings.welcomeMessage)Copy the code

What does Gradle become

The web library, as mentioned earlier in image Resources, provides a file called pubspec.yaml, which supports the rules.

Fragment and Activity?

For example, the MaterialApp is a bit like an Activity and the Scaffold is a bit like a Fragment. Both of these scaffolds are actually the Widgets of Flutter. That is to say, there is only the concept of View.

Is there a life cycle?

Flutter has a WidgetsBinding that provides life-cycle – like callbacks.

There are four states of inactive (iOS only), paused(onPause), resumed(onPostResume), and suspending(Android only).

Generally registered and unregistered in the State of StatefulWidgets.

 @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }Copy the code

ScrollView vs ListView

Flutter does not have a ScrollView, but incorporates it into ListView. ListView created from ListView.builder provides logic for View reuse.

ListView.builder(
          itemCount: widgets.length,
          itemBuilder: (BuildContext context, int position) {
            return Text(xxx);
          }))Copy the code

ItemBuilder is a bit like Android ListView’s getView. It automatically retrieves the Element back to you, but in fact you need to generate a new widget each time based on position. So, it seems that Flutter recyles the previous Widgets internally and uses them again when you recreate them.

BTW, with its ListView construction, does not have this feature, so a lot of data needs to be displayed with the Builder.

How to play Flutter horizontal and vertical screens.

Because it is in fact still using the story of the Android program, so if AndroidManifect defines the Android: configChanges = “orientation” | screenSize “, Flutter will hanlde himself.

How to handle Gesture

Flutter provides a GestureDetector, which acts as a Container that puts the Widgets we expect to receive gestures into and then implements event callbacks.

GestureDetector(Child: FlutterLogo(size: 200.0,), onTap: () {print("tap"); },)Copy the code

It also supports other gestures, such as onDoubleTap, and so on.

What about the font?

The first step is to configure the required font library in pubspec.yaml:

fonts:
   - family: MyCustomFont
     fonts:
       - asset: fonts/MyCustomFont.ttf
       - style: italicCopy the code

Then configure it in the style property of Text.

Text(
        'This is a custom font text',
        style: TextStyle(fontFamily: 'MyCustomFont'),
      )Copy the code

Where is Hint

The Hint for the input box is basically the same, perhaps with a different name.

TextField(
    decoration: InputDecoration(hintText: "This is a hint", errorText: _getErrorText()),
  )Copy the code

conclusion

Flutter takes a different approach to view rendering, with outstanding performance advantages. It is a dark horse in the cross-platform framework and backed by Google. It is worthy of those who have been working on Mobile for years.

Since the author has been working on Webkit development for 2 years, read the rendering mode of Flutter, which is very similar to the idea of Webkit/Chrome/Blink. After checking, it is found that there are lots of the same drafters. If you haven’t entered RN yet, Perhaps Flutter can be the first choice for cross-platform learning solutions.

Google also has a lot of plugins to support more extension functions, such as GPS, Camera, SharePreference, Database. There are also services like Firebase that fully support Flutter. These can be queried via Dartlang.

Of course, you can also develop your own Plugin to match the required function, based on the technology mentioned above MethodChannel, NDK support for the same reason.

Reference

https://flutter.io/docs/get-started/flutter-for/android-devs