“This is the sixth day of my participation in the First Challenge 2022. For details: First Challenge 2022”

This article introduces the function and usage of tag in GetX dependency injection.

role

The previous articles introduced the use of GetX dependency injection and analyzed the principle of dependency injection through the source code:

  • GetX integration and Usage of Flutter application framework
  • Flutter dissects the implementation of Getx dependency management step by step through the source code
  • Use of Flutter GetX dependency injection in detail

According to the source code, the main function of tag in GetX dependency injection is to distinguish between different instances of the same type of dependency. Similar to named in Dagger and koin.

GetX uses Map to cache dependencies. By default, the type name of the injected dependency is used as the key for caching. If the incoming tag is not empty, the combination of the type name and tag is used as the key for caching.

The key codes in the source code are as follows:

String _getKey(Type type, String? name) {
  return name == null ? type.toString() : type.toString() + name;
}
Copy the code

Where name is the tag passed in and type is the type of the dependent object.

If tag is used in dependency injection, you must add tag parameters to put and find, and the corresponding tag values are consistent to ensure that the injected and obtained dependent objects meet the expectations. Meanwhile, if you use GetBuilder as state management, you also need to pass in the corresponding tag value. Example code is as follows:

Get.put(CounterController(), tag: "counter");

CounterController controller = Get.find<CounterController>(tag: "counter");

GetBuilder<CounterController>(
        builder: (controller) {
          return Container();
        },
        tag: "counter");
Copy the code

Usage scenarios

Now that we’ve seen the use of tag, what kind of development scenarios would you use tag in? Here are two typical scenarios that I encountered during development.

Dependency injection of the same type with different functions

This scenario applies to existing types such as basic data, such as String and int. Although the type is the same, the use scenario or role in development is different.

For example, if the baseUrl and the token carried by the request authentication need to be injected into the network request, both have String types, but their functions and application scenarios are different. In this case, only one baseUrl will be injected without tag. In this case, you can use tag to distinguish whether to inject/obtain the baseUrl or token. Use as follows:

Get.put("http://juejin.cn", tag: "baseUrl");
Get.put(token, tag: "token");

Get.find(tag: "baseUrl");
Get.find(tag: "token");
Copy the code

Different instances of the same type and the same function

In this case, the injected dependencies are of the same type and have the same functions, but different instances are required for service reuse.

The common injected object in a page is Controller. In the case of page reuse, multiple pages may share one Controller without tag, because the default name of the dependent object type is used as the key. This will result in the same instance of Controller being injected by different pages. At this point, you can use tags to solve the problem.

For example, in a news detail interface, there is usually a list of related news in the news detail interface. When clicking the related news, it will jump to a new news detail interface. In the code, there is only one news detail interface, but different news IDS are passed in to display different news contents. If the dependency injection/acquisition is returned without tag, the content displayed in the new news details interface is still the same as that in the previous interface. Because the Controller instance obtained is the same, the data is the same and no new news content is loaded. The specific principle is described in detail in the previous principle article.

In this case, a tag is needed to solve the problem. The ID of the news can be used as a tag to ensure that different news shows their corresponding contents, and the same news data can be shared to avoid repeated loading of data.

A route forward carries a tag:

Get.to(NewsPage(tag: id,), arguments:{"id" : id});
Copy the code

NewPage gets dependencies:

class NewsPage extends StatelessWidget {

  final String? tag;
  final NewsController controller;
  NewsPage({Key? key, this.tag}) :
        controller = Get.put(NewsController(), tag: tag),
        super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text("News"),
        ),
        body: GetBuilder<NewsController>(
          builder: (controller) {
            return Container(); /// news content}, tag: tag, )); }}Copy the code

Get route parameters in Controller and load data:

class NewsController extends GetxController{
  @override
  void onInit() {
    super.onInit();
    var id = Get.arguments["id"];
    /// load new data}}Copy the code

If a Binding is used to inject dependencies, then a Binding also needs to be passed in a tag:

class NewsBinding extends Bindings{
  final String? tag;
  NewsBinding({this.tag});
  @override
  voiddependencies() { Get.lazyPut(() => NewsController(), tag: tag); }}Copy the code

Then when the route jumps:

Get.to(NewsPage(tag: id,), arguments:{"id" : id}, binding: NewsBinding(tag: id));
Copy the code

Interface access dependency:

class NewsPage extends StatelessWidget {

  final String? tag;
  const NewsPage({Key? key, this.tag}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    NewsController controller = Get.find(tag: tag);
    return Scaffold(
        appBar: AppBar(
          title: const Text("News"),
        ),
        body: GetBuilder<NewsController>(
          builder: (controller) {
            return Container(); /// news content}, tag: tag, )); }}Copy the code

In addition to the scenario where the details page jumps to the same page, and the page nesting reuse, this method can also be used to solve the dependency injection problem. For example, if the contents of page A are nested with page B and there are services to redirect to page B, the dependency injection problem can be flexibly solved by using tag. Essentially, there are different instances of the same page, as in the example described above.

conclusion

Flexible use of TAG in dependency injection can solve many complex business scenarios and improve code reuse.

More on GetX dependency injection portals:

  • GetX integration and Usage of Flutter application framework

  • Flutter dissects the implementation of Getx dependency management step by step through the source code

  • Use of Flutter GetX dependency injection in detail