preface

One of the most popular cross-platform frameworks these days uses a relatively obscure programming language called Dart. The DART language itself is heavily influenced by earlier programming languages. Especially Smalltalk,Java and JavaScript. I made the transition to Dart from the Java language and felt good at first, quickly gaining an understanding of the language and being able to write small pieces of code.

However, in the process of learning Flutter, I encountered a lot of confusion caused by some grammar of Dart. Looking back at dart’s syntax has led to some epiphanies that I’m writing down here in the hope of helping more learners.

What will you learn

  • Full and incomplete imports of external libraries
  • The impact of importing a new library on the variable namespace
  • Library split — part

The import

Complete the import

Let’s say we need to use some of the methods of library B in library A, and we need to import library B into library A. This is something we’re very familiar with.

import 'B.dart';
Copy the code

Not only that, dart’s import statements work with arbitrary urls. We can use one of the resources on the network (the DART file) as an external library import.

import 'http://hello/hello.dart';
Copy the code

But we don’t recommend it. Because network resources can change at any time. If we change it, our program will be broken.

The real rigor is:

import'package:hello/hello.dart';
Copy the code

Using package: The import approach executes a resident package manager that encapsulates the code location information.

All objects a library can use include those declared by the library itself and those imported from other libraries through import statements. Objects defined in DART: Core are implicitly imported. The objects that a library makes available to the outside world are called the library’s exported namespace.

Theoretically, a library namespace should not have two objects with the same name, otherwise you would need to use aliases.

import 'test2.dart'
class Test{
    static final hello = new Test();
}
Copy the code
class Test2{
    static final hello = new Test2();
    Test2 _test = new Test2();
}
Copy the code

In this code, Test2 is imported into the Test library. The Test2 private variable _test is not visible in the Test library, so it will not be imported into the namespace.

In Dart, objects declared by the current library take precedence over any other object, so having top-level objects in an imported library is not as disruptive as might be thought. But if you access an imported object and another import adds an object of the same name later, the new imported object overwrites the original object.

Incomplete import

Dart provides additional mechanisms to control what objects are imported into the library: the named combinators show and hide.

show

When we only need one or a few (few) objects from a large library, we can choose to use the Show combinator for import. This will make your library more robust.

import 'package:math' show Random;
Copy the code

In this line of code, we only import the Random object from the Math library.

The Show combinator takes a namespace and a list of identifiers, and keeps objects that appear in the list of identifiers in the namespace.

hide

When we do not want to import one or more objects in a library, we can use the hide combinator.

import 'package:math' hide Random;
Copy the code

This code imports the Math library but does not import Random objects of the Math library variety. The implementation is similar to show. It also takes a namespace and a list of identifiers, discards objects that appear in the list of identifiers from the namespace, and generates a new namespace.

Resolution of variable name conflicts

The best way to solve this problem is to alias the imported libraries.

import 'package:math' as mymath;
Copy the code

In this way we can perfectly avoid the problem of variable name conflicts between different libraries due to import.

Library of split

Sometimes a library may be too large to be easily stored in a single file. Dart allows us to split a library into one or more smaller part components. Or when we want some libraries to share their private objects, we need to use parts.

Not all libraries have names, but if you use part to build a library, then the library must be named.

library xxx;
Copy the code

Each subpart is stored in its own file. But they share the same scope, the internal namespace of the library, and all imports.

The following example uses a library split in Json deserialization.

// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'data.dart';

/ / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
// JsonSerializableGenerator
/ / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

Data _$DataFromJson(Map<String.dynamic> json) {
  return Data(
      by: json['by'] as String,
      descendants: json['descendants'] as int,
      id: json['id'] as int,
      kids: (json['kids'] as List)? .map((e) => eas int)? .toList(), score: json['score'] as int,
      time: json['time'] as int,
      title: json['title'] as String,
      type: json['type'] as String,
      url: json['url'] as String);
}

Map<String.dynamic> _$DataToJson(Data instance) => <String.dynamic> {'by': instance.by,
      'descendants': instance.descendants,
      'id': instance.id,
      'kids': instance.kids,
      'score': instance.score,
      'time': instance.time,
      'title': instance.title,
      'type': instance.type,
      'url': instance.url
    };


Copy the code

And then as part of data.dart.

import 'package:json_annotation/json_annotation.dart';
part 'data.g.dart';

@JsonSerializable(a)class Data{
  final String by;
  final int descendants;
  final int id;
  final List<int> kids;
  final int score;
  final int time;
  final String title;
  final String type;
  final String url;

  Data({this.by, this.descendants, this.id, this.kids, this.score, this.time,
    this.title, this.type, this.url});
// deserialize
  factory Data.fromJson(Map<String.dynamic> json) => _$DataFromJson(json);
/ / the serialization
  Map<String.dynamic> toJson() => _$DataToJson(this);
}

Copy the code

Dart data.g.art DataFromJson(json); dart data.g.art DataFromJson(json); The second part builds the DataFromJson(json) method and returns a Data object that is not defined in part data.g.art. They share a common namespace with each other. And private objects are also accessible to each other.

A part can also specify its library by URL, but this is also not recommended.

What is the difference between Part and import

Visibility: If library B is imported from library A, library A is not visible to library B. That is, library B is not aware of the existence of library A. The role of part is to break up a library into smaller components. Two or more parts together constitute a library, and they are aware of each other’s existence.

Scope: Imports do not fully share scope, while parts do. If library A imports library B and library B imports library C, there is no way for library A to directly use objects from library C. If B and C are parts of A, they share all objects. And includes all imports.

Write in the last

This is all about importing and splitting the Dart library. If there are any inaccuracies or errors, please correct them.

I will update a series of Flutter dry products later, if you like, please follow me or give me a good comment! I’ll be newer and more motivated.