Overview of Flutter Foundation

1, Basic concepts, references

The main development direction of FLUENT is the mobile end cross platform scheme. The implementation language of FLUENT is dart, and the supported languages on the native side are java and kotlin on the Android side, oc and swift on the ios side.
Refer to the official website:
https://flutterchina.club/docs/
https://flutter.dev/docs

Dependent warehouse address:
https://pub.dev/
This address has all dart dependency repositories, and the notification also hosts all flutter public dependencies.

2, Main modules

  1. Basic grammar
    In fluent, everything is a widget, including basic components, layout components and style components, which are all defined by widgets. This brings some problems. Styles and ui are mixed together. If your team does not set some constraints and set some public styles, it will be confusing in engineering.
  • text
Text("I am a text", style:TextStyle(fontSize:12,color:Colors(0xff333333)));
  • image
Image(image: AssetImage("images/my_image.png", package: 'my_package_name'));
Image(image: NetworkImage("https://xxx.xxx.xxx.png"));
  • button
Botton(
	onTap:()=>{//dosomething},
	image:Image.asset("xxxx.png"),
	title:Text("xxxx"),
);
  • Style layout
Column(
            mainAxisAlignment: MainAxisAlignment.start,
            crossAxisAlignment: CrossAxisAlignment.center,
            children:[
				Text(...),
				Button(...),
				Row(...),
			],
			padding:const EdgeInsets.fromLTRB(20, 30, 20, 20),
);
///	container
///	row
  1. Project type
    A warehouse template can be created by using the instruction fluent create - T. there are several types of warehouses. Refer to the description of fluent create - H and list them as follows
  • app (default) Generate a Flutter application.
    Main works
  • module Generate a project to add a Flutter module to an existing Android or iOS application.
    If you want to add the fluent code to the existing Android and iOS projects, you can use this warehouse template
  • puglin Generate a shareable Flutter project containing an API in Dart code with a platform-specific implementation for Android, for iOS code, or for both.
    Repository containing Android or iOS implementations
  • package Generate a shareable Flutter project containing modular Dart code.
    A repository containing only dart code. This repository can create two hidden folders. android and. ios as the running environment for testing
  • skeleton Generate a List View / Detail View Flutter application that follows community best practices.
    Not used
  1. State management
  • StatelessWidget and StatefulWidget
    For components that do not need to be changed, use StatelessWidget.
    For components that may have state changes, use StatefulWidget.
	class VariedWidget extends StatefulWidget {
	  @override
	  State<StatefulWidget> createState() {
	    return VariedState();
	  }
	}
	
	class VariedState extends State<VariedWidget> {
	  String _state = "before";
	
	  @override
	  Widget build(BuildContext context) {
	    return Column(
	      children: [
	        Text(_state),
	        TextButton(
	            onPressed: () => {
	                  setState(() {
	                    _state = "after";
	                  })
	                },
	            child: Text('Click to change the status'))
	      ],
	    );
	  }
	}
  • Shared state management Provider
  • Introduction to state management framework
    Provider is an official solution to share the state of multiple components. Understanding it can also help us understand the state management framework of other third parties
    The above two points refer to the document I prepared
    https://docs.qq.com/doc/DRUxseWhXQ2FZWHdi
  1. Routing management
  • navigator
    For the official basic scheme, see Navigator.dart for more details. Example of official website:
	import 'package:flutter/material.dart';
	
	// ...
	
	void main() => runApp(const MyApp());
	
	// ...
	
	class MyApp extends StatelessWidget {
	  const MyApp({Key? key}) : super(key: key);
	
	  @override
	  Widget build(BuildContext context) {
	    return MaterialApp(
	      title: 'Flutter Code Sample for Navigator',
	      // MaterialApp contains our top-level Navigator
	      initialRoute: '/',
	      routes: <String, WidgetBuilder>{
	        '/': (BuildContext context) => const HomePage(),
	        '/signup': (BuildContext context) => const SignUpPage(),
	      },
	    );
	  }
	}
	
	class HomePage extends StatelessWidget {
	  const HomePage({Key? key}) : super(key: key);
	
	  @override
	  Widget build(BuildContext context) {
	    return DefaultTextStyle(
	      style: Theme.of(context).textTheme.headline4!,
	      child: Container(
	        color: Colors.white,
	        alignment: Alignment.center,
	        child: const Text('Home Page'),
	      ),
	    );
	  }
	}
	
	class CollectPersonalInfoPage extends StatelessWidget {
	  const CollectPersonalInfoPage({Key? key}) : super(key: key);
	
	  @override
	  Widget build(BuildContext context) {
	    return DefaultTextStyle(
	      style: Theme.of(context).textTheme.headline4!,
	      child: GestureDetector(
	        onTap: () {
	          // This moves from the personal info page to the credentials page,
	          // replacing this page with that one.
	          Navigator.of(context)
	            .pushReplacementNamed('signup/choose_credentials');
	        },
	        child: Container(
	          color: Colors.lightBlue,
	          alignment: Alignment.center,
	          child: const Text('Collect Personal Info Page'),
	        ),
	      ),
	    );
	  }
	}
	
	class ChooseCredentialsPage extends StatelessWidget {
	  const ChooseCredentialsPage({
	    Key? key,
	    required this.onSignupComplete,
	  }) : super(key: key);
	
	  final VoidCallback onSignupComplete;
	
	  @override
	  Widget build(BuildContext context) {
	    return GestureDetector(
	      onTap: onSignupComplete,
	      child: DefaultTextStyle(
	        style: Theme.of(context).textTheme.headline4!,
	        child: Container(
	          color: Colors.pinkAccent,
	          alignment: Alignment.center,
	          child: const Text('Choose Credentials Page'),
	        ),
	      ),
	    );
	  }
	}
	
	class SignUpPage extends StatelessWidget {
	  const SignUpPage({Key? key}) : super(key: key);
	
	  @override
	  Widget build(BuildContext context) {
	    // SignUpPage builds its own Navigator which ends up being a nested
	    // Navigator in our app.
	    return Navigator(
	      initialRoute: 'signup/personal_info',
	      onGenerateRoute: (RouteSettings settings) {
	        WidgetBuilder builder;
	        switch (settings.name) {
	          case 'signup/personal_info':
	          // Assume CollectPersonalInfoPage collects personal info and then
	          // navigates to 'signup/choose_credentials'.
	            builder = (BuildContext context) => const CollectPersonalInfoPage();
	            break;
	          case 'signup/choose_credentials':
	          // Assume ChooseCredentialsPage collects new credentials and then
	          // invokes 'onSignupComplete()'.
	            builder = (BuildContext _) => ChooseCredentialsPage(
	              onSignupComplete: () {
	                // Referencing Navigator.of(context) from here refers to the
	                // top level Navigator because SignUpPage is above the
	                // nested Navigator that it created. Therefore, this pop()
	                // will pop the entire "sign up" journey and return to the
	                // "/" route, AKA HomePage.
	                Navigator.of(context).pop();
	              },
	            );
	            break;
	          default:
	            throw Exception('Invalid route: ${settings.name}');
	        }
	        return MaterialPageRoute<void>(builder: builder, settings: settings);
	      },
	    );
	  }
	}

Reference API: https://api.flutter.dev/flutter/widgets/Navigator-class.html Basically, most common routing requirements can be solved, but one disadvantage is that context needs to be passed in every use. Some frameworks can solve this problem.

  • Introduction to routing framework
    GetX can be used as a relatively fast routing encapsulation tool. It is recommended to add the encapsulation of jumping to the native page.
  1. Network request
  • http
  • Introduction to dio framework
  1. Internationalization, theme management
  • Basic usage
    internationalization: https://flutterchina.club/tutorials/internationalization/
    Topic management: use Provider
  • Use frame GetX
    GetX also has internationalization and theme management capabilities. reference resources: https://github.com/jonataslaw/getx/blob/master/README.zh-cn.md
  1. Custom components
  1. Code specification
  • Naming conventions
  • Subcontract specification
  • Reference specification
    reference resources: https://github.com/alibaba/flutter-go/blob/master/Flutter_Go%20%E4%BB%A3%E7%A0%81%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83.md
    https://dart.cn/guides/language/effective-dart/style
  1. unit testing
  • dart test
  • widget test
  • integration testing
    reference resources: https://flutterchina.club/testing/
  1. Build packaging
    reference resources: https://flutterchina.club/android-release/

3, Introduction to air safety

dart empty security is a constraint. If a dependency does not support empty security, the whole project cannot be built in the form of empty security. Therefore, in order for the project to use the null security feature, all dependencies of the whole project are required to follow the null security constraint.

4, Some features and constraints brought by dart

  1. Expansion method
    extension keyword can add new methods to existing classes
  2. In order to reduce the volume of the build package, the classes that do not directly establish dependencies will be eliminated in the build, and reflection can refer to all classes. The trade-off made by flutter is to disable dart's mirror library.
  3. Type inference questions
    When using generics, if a parameter requires the use of the specified t extensions xxx, it seems that an error will also be reported if xxx is directly passed in. This is a strange feature
  4. Resource path management
    Image when loading resource images, it is better not to use absolute paths, but to specify the package name with package, and then use relative paths. Otherwise, the image will not be displayed if it is referenced in different paths.

5, Feeling brought by flutter development

Because hot loading can refresh the page display in real time, developing the page is very fast.
However, not all code adjustments support hot loading, such as changes to nested root App widget classes (the same as rn), such as resource changes.

Fluent cannot use reflection, so parsing json classes is particularly cumbersome. Generally, plug-ins or tools are used to automatically generate parsing code.

Like rn, fluent solves the cross platform problem. Write the business once, which can be applied to both ends, reducing the development time and testing pressure.

But I think rn has an advantage over flitter.
The principles of the two schemes are different,
RN uses virtual dom to map into native component pages to realize cross platform.
Fluent is a dart engine that renders all pages by itself to achieve cross platform.

  1. rn has better compatibility with native. It has great advantages when making native custom components. It can be perfectly compatible with all native components.
    There are still many bug s when the fluent is embedded in the native view, such as the soft keyboard can not monitor the pop-up, etc.

  2. Moreover, the rn community should be larger, because as long as react is the front end, it is easy to master writing. flutter needs to learn dart syntax alone. Although dart is very simple, dart also has many counterintuitive constraints, such as the problem of generics.

If I am allowed to write my own project, I may choose fluent for rapid development, but as a project that wants long-term support and does not think of problems, I will choose rn.

Tags: iOS Android Flutter

Posted on Tue, 28 Sep 2021 02:31:37 -0400 by acidHL