“This is the fourth day of my participation in the First Challenge 2022. For details: First Challenge 2022”
GetX dependency injection implementation principle is analyzed by 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
After understanding the principles of GetX dependency injection, this article will cover the use of GetX dependency injection in detail through different injection methods and parameter Settings.
put
In order to verify the dependency injection function, first create two test pages: PageA and PageB, PageA add two buttons toB and find, respectively jump PageB and get dependency; Dependency objects are injected through the PUT method in PageB, and a button is invoked to trigger Find to retrieve the dependency. Key source code is as follows:
PageA:
TextButton(
child: const Text("toB"),
onPressed: (){
/// Navigator.push(context, MaterialPageRoute(builder: (context) => const PageB()));
/// Get.to(const PageB());
},
),
TextButton(
child: const Text("find"),
onPressed: () async {
User user = Get.find();
print("page a username : ${user.name} id: ${user.id}");
})
Copy the code
PageB:
Get.put(User.create("Zhang".DateTime.now().millisecondsSinceEpoch)));
User user = Get.find();
TextButton(
child: const Text("find"),
onPressed: (){
User user = Get.find();
print("${DateTime.now()} page b username : ${user.name} id: ${user.id}");
})
Copy the code
Where User is a user-defined object, used for test injection, the source code is as follows:
User:
class User{
final String? name;
final int? id;
factory User.create(String name, int id){
print("${DateTime.now()} create User");
returnUser(name, id); }}Copy the code
Navigator Route jump
Use the route management of Flutter to jump from PageA to PageB, then return to PageA and click the find button to obtain the User dependencies:
Navigator.push(context, MaterialPageRoute(builder: (context) => const PageB()));
Copy the code
Process: PageA -> PageB -> PUT -> find -> PageA -> find
Output result:
/// put
I/flutter (31878) :2022- 0127 - 19:18:20.851800 create User
[GETX] Instance "User" has been created
/// page b find
I/flutter (31878) :2022- 0127 - 19:18:22.170133Page B username:1643282300139
/// page a find
I/flutter (31878) :2022- 0127 - 19:18:25.554667Page a username:1643282300139
Copy the code
The dependency User injected in PageB can still be retrieved by find after PageA is returned, and it is the same object. Dependencies can be retrieved when a page is destroyed, but why does PageA return to the page to retrieve dependencies? This is because recycling at page destruction is based on using GetX’s route management page, and page destruction using the official Navigator does not trigger recycling dependencies.
GetX Indicates the route forward
Do the same with GetX and look at the output:
Get.to(const PageB());
Copy the code
Process: PageA -> PageB -> PUT -> find -> PageA -> find
Output result:
[GETX] GOING TO ROUTE /PageB
/// put
I/flutter (31878) :2022- 0127 - 19:16:32.014530 create User
[GETX] Instance "User" has been created
/// page b find
I/flutter (31878) :2022- 0127 - 19:16:34.043144Page B username:1643282192014
[GETX] CLOSE TO ROUTE /PageB
[GETX] "User" deleted from memory
/// page a find error
E/flutter (31878): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: "User" not found. You need to call "Get.put(User())" or "Get.lazyPut(()=>User())"
Copy the code
Deleted from memory the User was deleted from PageB, and the User was deleted from PageB via find. You need to call PUT or lazyPut to inject dependent objects first. This verifies that when using GetX to route jumps and using PUT to inject dependencies by default, dependencies will also be reclaimed when the page destroys them.
permanent
Put also has a permanent parameter, which is used to create a Flutter. The default value is false. The permanent parameter is set to true when a Flutter is put. And repeat the process using GetX’s route jump as well.
Key code:
Get.put(User.create("Zhang".DateTime.now().millisecondsSinceEpoch), permanent: true);
Copy the code
Process: PageA -> PageB -> PUT -> find -> PageA -> find
Output result:
[GETX] GOING TO ROUTE /PageB
/// put
I/flutter (31878) :2022- 0127 - 19:15:16.110403 create User
[GETX] Instance "User" has been created
/// page b find
I/flutter (31878) :2022- 0127 - 19:15:18.667360Page B username:1643282116109
[GETX] CLOSE TO ROUTE /PageB
[GETX] "User" has been marked as permanent, SmartManagement is not authorized to delete it.
/// page a find success
I/flutter (31878): page a username:1643282116109
Copy the code
If permanent is set to true, the dependency object will be returned to PageA as well, indicating that the dependency was not recovered due to page destruction. If permanent is set to true, the dependency object will not be deleted. “User” has been marked as permanent, SmartManagement is not authorized to delete it.
lazyPut
LazyPut is a lazy initialization dependent object:
Get.lazyPut(() => User.create("Zhang".DateTime.now().millisecondsSinceEpoch));
TextButton(
child: const Text("find"),
onPressed: () async {
User user = Get.find();
print("${DateTime.now()} page b username : ${user.name} id: ${user.id}");
})
Copy the code
Process: PageA – > PageB – > put – > find – > find – > PageA – > find, from PageA jump PageB, through lazyPut injection first, and then click the find for a rely on, click on it again in three seconds, Then go back to PageA and click Find to get it once.
Output result:
[GETX] GOING TO ROUTE /PageB
/// lazyPut
/// page b find 1
I/flutter (31878) :2022- 0127 - 17:38:49.590295 create User
[GETX] Instance "User" has been created
I/flutter (31878) :2022- 0127 - 17:38:49.603063Page B username:1643276329589
/// page b find 2
I/flutter (31878) :2022- 0127 - 17:38:52.297049Page B username:1643276329589
[GETX] CLOSE TO ROUTE /PageB
[GETX] "User" deleted from memory
/// page a find error
E/flutter (31878): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: "User" not found. You need to call "Get.put(User())" or "Get.lazyPut(()=>User())"
Copy the code
The User object is initialized on the first call to find. The User object is not initialized on the second call to find. Similarly, dependencies are reclaimed when PageB is destroyed, resulting in an error in PageA.
fenix
LazyPut also has a Fenix argument, false by default, that removes dependencies when destroyed, but recreates them the next time you find them.
LazyPut adds the Fenix argument:
Get.lazyPut(() => User.create("Zhang".DateTime.now().millisecondsSinceEpoch), fenix: true);
Copy the code
Process: PageA -> PageB -> PUT -> find -> find -> PageA -> find, same as the previous process.
Output result:
[GETX] GOING TO ROUTE /PageB
/// lazyPut
/// page b find 1
[GETX] Instance "User" has been created
I/flutter (31878) :2022- 0127 - 17:58:58.321564 create User
I/flutter (31878) :2022- 0127 - 17:58:58.333369Page B username:1643277538321
/// page b find 2
I/flutter (31878) :2022- 0127 - 17:59:01.647629Page B username:1643277538321
[GETX] CLOSE TO ROUTE /PageB
/// page a find success
I/flutter (31878) :2022- 0127 - 17:59:07.666929 create User
[GETX] Instance "User" has been created
I/flutter (31878): page a username:1643277547666
Copy the code
By analyzing the output log, the performance in PageB is consistent with that without Fenix, but returning PageA to get the dependency does not report an error, but rather re-creates the dependency object. That’s where Fenix comes in.
putAsync
PutAsync is basically the same as PUT, except that incoming dependencies can be initialized asynchronously. The test code is modified as follows:
print("${DateTime.now()} : page b putAsync User");
Get.putAsync(() async {
await Future.delayed(const Duration(seconds: 3));
return User.create("Zhang".DateTime.now().millisecondsSinceEpoch);
});
Copy the code
Simulate time-consuming operations using future.delayed.
Process: PageA -> PageB -> PUT -> find -> PageA -> find
Output result:
[GETX] GOING TO ROUTE /PageB
/// putAsync
I/flutter (31878) :2022- 0127 - 18:48:34.280337 : page b putAsync User
/// create user
I/flutter (31878) :2022- 0127 - 18:48:37.306073 create User
[GETX] Instance "User" has been created
/// page b find
I/flutter (31878) :2022- 0127 - 18:48:40.264854Page B username:1643280517305
[GETX] CLOSE TO ROUTE /PageB
[GETX] "User" deleted from memory
/// page a find error
E/flutter (31878): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: "User" not found. You need to call "Get.put(User())" or "Get.lazyPut(()=>User())"
Copy the code
The log shows that the User is created 3s after put.
create
Create’s permanent parameter is set to true by default, but isSingleton is set to false when the Flutter is called internally. That is, the dependent object is recreated each time we find it.
Get.create(() => User.create("Zhang".DateTime.now().millisecondsSinceEpoch));
Copy the code
Process: PageA -> PageB -> PUT -> find -> find -> PageA -> find
Output result:
[GETX] GOING TO ROUTE /PageB
/// create
/// page b find 1
I/flutter (31878) :2022- 0127 - 18:56:10.520961 create User
I/flutter (31878) :2022- 0127 - 18:56:10.532465Page B username:1643280970520
/// page b find 2
I/flutter (31878) :2022- 0127 - 18:56:18.933750 create User
I/flutter (31878) :2022- 0127 - 18:56:18.934188Page B username:1643280978933
[GETX] CLOSE TO ROUTE /PageB
/// page a find success
I/flutter (31878) :2022- 0127 - 18:56:25.319224 create User
I/flutter (31878): page a username:1643280985319
Copy the code
As you can see from the log, the User object is indeed recreated every time you find, and you can retrieve dependent objects from find after you exit PageB.
conclusion
Call different injection methods, set different parameters, and analyze the output logs. The specific functions of put, lazyPut, putAsync, create, permanent, and Fenix parameters are described in detail. Different injection methods can be flexibly used in development according to actual business scenarios. The injected tag parameters will be covered in more detail in a future article.