Jonatas

Allow lazyPut to recognize the instance type automatically if no type is provided

Showing 36 changed files with 749 additions and 184 deletions
@@ -96,7 +96,7 @@ Get.put<S>( @@ -96,7 +96,7 @@ Get.put<S>(
96 bool overrideAbstract = false, 96 bool overrideAbstract = false,
97 97
98 // optional: allows you to create the dependency using function instead of the dependency itself. 98 // optional: allows you to create the dependency using function instead of the dependency itself.
99 - FcBuilderFunc<S> builder, 99 + InstanceBuilderCallback<S> builder,
100 ) 100 )
101 ``` 101 ```
102 102
@@ -106,7 +106,7 @@ Get.put<S>( @@ -106,7 +106,7 @@ Get.put<S>(
106 Get.lazyPut<S>( 106 Get.lazyPut<S>(
107 // mandatory: a method that will be executed when your class is called for the first time 107 // mandatory: a method that will be executed when your class is called for the first time
108 // Example: Get.lazyPut<Controller>( () => Controller() ) 108 // Example: Get.lazyPut<Controller>( () => Controller() )
109 - FcBuilderFunc builder, 109 + InstanceBuilderCallback builder,
110 110
111 // optional: same as Get.put(), it is used for when you want multiple different instance of a same class 111 // optional: same as Get.put(), it is used for when you want multiple different instance of a same class
112 // must be unique 112 // must be unique
@@ -128,7 +128,7 @@ Get.putAsync<S>( @@ -128,7 +128,7 @@ Get.putAsync<S>(
128 128
129 // mandatory: an async method that will be executed to instantiate your class 129 // mandatory: an async method that will be executed to instantiate your class
130 // Example: Get.putAsync<YourAsyncClass>( () async => await YourAsyncClass() ) 130 // Example: Get.putAsync<YourAsyncClass>( () async => await YourAsyncClass() )
131 - FcBuilderFuncAsync<S> builder, 131 + AsyncInstanceBuilderCallback<S> builder,
132 132
133 // optional: same as Get.put(), it is used for when you want multiple different instance of a same class 133 // optional: same as Get.put(), it is used for when you want multiple different instance of a same class
134 // must be unique 134 // must be unique
@@ -99,7 +99,7 @@ Get.put<S>( @@ -99,7 +99,7 @@ Get.put<S>(
99 bool overrideAbstract = false, 99 bool overrideAbstract = false,
100 100
101 // optional: allows you to create the dependency using function instead of the dependency itself. 101 // optional: allows you to create the dependency using function instead of the dependency itself.
102 - FcBuilderFunc<S> builder, 102 + InstanceBuilderCallback<S> builder,
103 ) 103 )
104 ``` 104 ```
105 105
@@ -109,7 +109,7 @@ Get.put<S>( @@ -109,7 +109,7 @@ Get.put<S>(
109 Get.lazyPut<S>( 109 Get.lazyPut<S>(
110 // mandatory: a method that will be executed when your class is called for the first time 110 // mandatory: a method that will be executed when your class is called for the first time
111 // Example: Get.lazyPut<Controller>( () => Controller() ) 111 // Example: Get.lazyPut<Controller>( () => Controller() )
112 - FcBuilderFunc builder, 112 + InstanceBuilderCallback builder,
113 113
114 // optional: same as Get.put(), it is used for when you want multiple different instance of a same class 114 // optional: same as Get.put(), it is used for when you want multiple different instance of a same class
115 // must be unique 115 // must be unique
@@ -131,7 +131,7 @@ Get.putAsync<S>( @@ -131,7 +131,7 @@ Get.putAsync<S>(
131 131
132 // mandatory: an async method that will be executed to instantiate your class 132 // mandatory: an async method that will be executed to instantiate your class
133 // Example: Get.putAsync<YourAsyncClass>( () async => await YourAsyncClass() ) 133 // Example: Get.putAsync<YourAsyncClass>( () async => await YourAsyncClass() )
134 - FcBuilderFuncAsync<S> builder, 134 + AsyncInstanceBuilderCallback<S> builder,
135 135
136 // optional: same as Get.put(), it is used for when you want multiple different instance of a same class 136 // optional: same as Get.put(), it is used for when you want multiple different instance of a same class
137 // must be unique 137 // must be unique
@@ -96,7 +96,7 @@ Get.put<S>( @@ -96,7 +96,7 @@ Get.put<S>(
96 bool permanent = false, 96 bool permanent = false,
97 97
98 // opcional: permite criar a dependência usando uma função em vez da dependênia em si 98 // opcional: permite criar a dependência usando uma função em vez da dependênia em si
99 - FcBuilderFunc<S> builder, 99 + InstanceBuilderCallback<S> builder,
100 ) 100 )
101 ``` 101 ```
102 102
@@ -106,7 +106,7 @@ Get.put<S>( @@ -106,7 +106,7 @@ Get.put<S>(
106 Get.lazyPut<S>( 106 Get.lazyPut<S>(
107 // obrigatório: um método que vai ser executado quando sua classe é chamada pela primeira vez 107 // obrigatório: um método que vai ser executado quando sua classe é chamada pela primeira vez
108 // Exemplo: "Get.lazyPut<Controller>( () => Controller() 108 // Exemplo: "Get.lazyPut<Controller>( () => Controller()
109 - FcBuilderFunc builder, 109 + InstanceBuilderCallback builder,
110 110
111 // opcional: igual ao Get.put(), é usado quando você precisa de múltiplas instâncias de uma mesma classe 111 // opcional: igual ao Get.put(), é usado quando você precisa de múltiplas instâncias de uma mesma classe
112 // precisa ser uma string única 112 // precisa ser uma string única
@@ -127,7 +127,7 @@ Get.lazyPut<S>( @@ -127,7 +127,7 @@ Get.lazyPut<S>(
127 Get.putAsync<S>( 127 Get.putAsync<S>(
128 // Obrigatório: um método assíncrono que vai ser executado para instanciar sua classe 128 // Obrigatório: um método assíncrono que vai ser executado para instanciar sua classe
129 // Exemplo: Get.putAsyn<YourAsyncClass>( () async => await YourAsyncClass() ) 129 // Exemplo: Get.putAsyn<YourAsyncClass>( () async => await YourAsyncClass() )
130 - FcBuilderFuncAsync<S> builder, 130 + AsyncInstanceBuilderCallback<S> builder,
131 131
132 // opcional: igual ao Get.put(), é usado quando você precisa de múltiplas instâncias de uma mesma classe 132 // opcional: igual ao Get.put(), é usado quando você precisa de múltiplas instâncias de uma mesma classe
133 // precisa ser uma string única 133 // precisa ser uma string única
@@ -144,7 +144,7 @@ Get.putAsync<S>( @@ -144,7 +144,7 @@ Get.putAsync<S>(
144 Get.create<S>( 144 Get.create<S>(
145 // Obrigatório: Uma função que retorna uma classe que será "fabricada" toda vez que Get.find() for chamado 145 // Obrigatório: Uma função que retorna uma classe que será "fabricada" toda vez que Get.find() for chamado
146 // Exemplo: Get.create<YourClass>(() => YourClass()) 146 // Exemplo: Get.create<YourClass>(() => YourClass())
147 - FcBuilderFunc<S> builder, 147 + InstanceBuilderCallback<S> builder,
148 148
149 // opcional: igual ao Get.put(), mas é usado quando você precisa de múltiplas instâncias de uma mesma classe. 149 // opcional: igual ao Get.put(), mas é usado quando você precisa de múltiplas instâncias de uma mesma classe.
150 // Útil caso você tenha uma lista em que cada item precise de um controller próprio 150 // Útil caso você tenha uma lista em que cada item precise de um controller próprio
@@ -170,7 +170,7 @@ A diferença fundamental entre `permanent` e `fenix` está em como você quer ar @@ -170,7 +170,7 @@ A diferença fundamental entre `permanent` e `fenix` está em como você quer ar
170 170
171 Prosseguindo com as diferenças entre os métodos: 171 Prosseguindo com as diferenças entre os métodos:
172 172
173 -- Get.put e Get.putAsync seguem a mesma ordem de criação, com a diferença que o Async opta por aplicar um método assíncrono: Esses dois métodos criam e já inicializam a instância. Esta é inserida diretamente na memória, através do método interno `insert` com os parâmetros `permanent: false` e `isSingleton: true` (esse parâmetro `isSingleton` serve apenas para dizer se é para utilizar a dependência colocada em `dependency`, ou se é para usar a dependência colocada no `FcBuilderFunc`). Depois disso, é chamado o `Get.find` que imediatamente inicializa as instâncias que estão na memória. 173 +- Get.put e Get.putAsync seguem a mesma ordem de criação, com a diferença que o Async opta por aplicar um método assíncrono: Esses dois métodos criam e já inicializam a instância. Esta é inserida diretamente na memória, através do método interno `insert` com os parâmetros `permanent: false` e `isSingleton: true` (esse parâmetro `isSingleton` serve apenas para dizer se é para utilizar a dependência colocada em `dependency`, ou se é para usar a dependência colocada no `InstanceBuilderCallback`). Depois disso, é chamado o `Get.find` que imediatamente inicializa as instâncias que estão na memória.
174 174
175 - Get.create: Como o nome indica, você vai "criar" a sua dependência! Similar ao `Get.put`, ela também chama o método interno `insert` para instanciamento. Contudo, `permanent` e `isSingleton` passam a ser `true` e `false` (Como estamos "criando" a nossa dependência, não tem como ela ser um Singleton de algo, logo, `false`). E por ser `permanent: true`, temos por padrão o benefício de não se perder entre telas! Além disso, não é chamado o `Get.find`, logo ela fica esperando ser chamada para ser usada. Ele é criado dessa forma para aproveitar o uso do parâmetro `permanent`, já que, vale ressaltar, o Get.create foi criado com o objetivo de criar instâncias não compartilhadas, mas que não se perdem, como por exemplo um botão em um listView, que você quer uma instância única para aquela lista - por conta disso, o Get.create deve ser usado em conjunto com o GetWidget. 175 - Get.create: Como o nome indica, você vai "criar" a sua dependência! Similar ao `Get.put`, ela também chama o método interno `insert` para instanciamento. Contudo, `permanent` e `isSingleton` passam a ser `true` e `false` (Como estamos "criando" a nossa dependência, não tem como ela ser um Singleton de algo, logo, `false`). E por ser `permanent: true`, temos por padrão o benefício de não se perder entre telas! Além disso, não é chamado o `Get.find`, logo ela fica esperando ser chamada para ser usada. Ele é criado dessa forma para aproveitar o uso do parâmetro `permanent`, já que, vale ressaltar, o Get.create foi criado com o objetivo de criar instâncias não compartilhadas, mas que não se perdem, como por exemplo um botão em um listView, que você quer uma instância única para aquela lista - por conta disso, o Get.create deve ser usado em conjunto com o GetWidget.
176 176
1 -import 'package:get/get.dart';  
2 -import '../data/home_model.dart';  
3 -import '../data/home_repository.dart';  
4 -  
5 -class HomeController extends GetxController {  
6 - HomeController({this.homeRepository});  
7 - final HomeRepository homeRepository;  
8 -  
9 - Rx<ApiModel> data = Rx<ApiModel>();  
10 -  
11 - @override  
12 - void onInit() => fetchDataFromApi();  
13 -  
14 - void fetchDataFromApi() async {  
15 - data.value = await homeRepository.getData();  
16 - if (data.value == null) {  
17 - Get.snackbar("Error", "Can't connect to server");  
18 - }  
19 - }  
20 -}  
1 -import 'package:dio/dio.dart';  
2 -import 'package:flutter/foundation.dart';  
3 -import 'home_model.dart';  
4 -  
5 -abstract class IHomeProvider {  
6 - Future<ApiModel> get();  
7 - Future<ApiModel> post(Map<String, dynamic> data);  
8 - Future<ApiModel> put(Map<String, dynamic> data);  
9 - Future<ApiModel> delete(int id);  
10 -}  
11 -  
12 -class HomeProvider implements IHomeProvider {  
13 - final Dio dio;  
14 -  
15 - HomeProvider({@required this.dio});  
16 -  
17 - Future<ApiModel> get() async {  
18 - try {  
19 - final response = await dio.get("https://api.covid19api.com/summary");  
20 - return ApiModel.fromJson(response.data);  
21 - } catch (e) {  
22 - print(e.toString());  
23 - return null;  
24 - }  
25 - }  
26 -  
27 - @override  
28 - Future<ApiModel> post(Map<String, dynamic> data) {  
29 - throw UnimplementedError();  
30 - }  
31 -  
32 - @override  
33 - Future<ApiModel> put(Map<String, dynamic> data) {  
34 - throw UnimplementedError();  
35 - }  
36 -  
37 - @override  
38 - Future<ApiModel> delete(int id) {  
39 - throw UnimplementedError();  
40 - }  
41 -}  
1 -import 'home_model.dart';  
2 -import 'home_provider.dart';  
3 -  
4 -class HomeRepository {  
5 - HomeRepository({this.homeProvider});  
6 - final HomeProvider homeProvider;  
7 -  
8 - Future<ApiModel> getData() async {  
9 - return homeProvider.get();  
10 - }  
11 -}  
1 import 'package:flutter/material.dart'; 1 import 'package:flutter/material.dart';
2 import 'package:get/get.dart'; 2 import 'package:get/get.dart';
3 -import 'package:get_state/home/bindings/home_binding.dart';  
4 -import 'package:get_state/home/views/country_view.dart';  
5 -import 'home/views/details_view.dart';  
6 -import 'home/views/home_view.dart'; 3 +import 'package:get_state/routes/app_pages.dart';
  4 +import 'shared/logger/logger_utils.dart';
7 5
8 void main() { 6 void main() {
9 - runApp(  
10 - GetMaterialApp( 7 + runApp(MyApp());
  8 +}
  9 +
  10 +class MyApp extends StatelessWidget {
  11 + const MyApp({Key key}) : super(key: key);
  12 +
  13 + @override
  14 + Widget build(BuildContext context) {
  15 + return GetMaterialApp(
11 debugShowCheckedModeBanner: false, 16 debugShowCheckedModeBanner: false,
12 - initialRoute: '/',  
13 enableLog: true, 17 enableLog: true,
14 - // logWriterCallback: localLogWriter,  
15 - getPages: [  
16 - GetPage(name: '/', page: () => HomePage(), binding: HomeBinding()),  
17 - GetPage(name: '/country', page: () => CountryPage()),  
18 - GetPage(name: '/details', page: () => DetailsPage()),  
19 - ],  
20 - ), 18 + logWriterCallback: Logger.write,
  19 + initialRoute: AppPages.INITIAL,
  20 + getPages: AppPages.routes,
21 ); 21 );
22 -}  
23 -  
24 -// Sample of abstract logging function  
25 -void localLogWriter(String text, {bool isError = false}) {  
26 - print('** ' + text + ' [' + isError.toString() + ']'); 22 + }
27 } 23 }
1 import 'package:dio/dio.dart'; 1 import 'package:dio/dio.dart';
2 import 'package:get/get.dart'; 2 import 'package:get/get.dart';
3 -import '../controllers/home_controller.dart';  
4 -import '../data/home_provider.dart'; 3 +import 'package:get_state/pages/home/domain/adapters/repository_adapter.dart';
  4 +import 'package:get_state/pages/home/presentation/controllers/home_controller.dart';
5 import '../data/home_repository.dart'; 5 import '../data/home_repository.dart';
6 6
7 class HomeBinding extends Bindings { 7 class HomeBinding extends Bindings {
8 @override 8 @override
9 void dependencies() { 9 void dependencies() {
10 - Get.lazyPut<HomeController>(() {  
11 - Get.put(Dio());  
12 - Get.put(HomeProvider(dio: Get.find()));  
13 - Get.put(HomeRepository(homeProvider: Get.find()));  
14 - return HomeController(homeRepository: Get.find());  
15 - }); 10 + Get.lazyPut(() => Dio());
  11 + Get.lazyPut<IHomeRepository>(() => HomeRepository(dio: Get.find()));
  12 + Get.lazyPut(() => HomeController(homeRepository: Get.find()));
16 } 13 }
17 } 14 }
  1 +import 'package:dio/dio.dart';
  2 +import 'package:get_state/pages/home/domain/adapters/repository_adapter.dart';
  3 +import 'package:get_state/pages/home/domain/entity/cases_model.dart';
  4 +
  5 +class HomeRepository implements IHomeRepository {
  6 + HomeRepository({this.dio});
  7 + final Dio dio;
  8 +
  9 + @override
  10 + Future<CasesModel> getCases() async {
  11 + try {
  12 + final response = await dio.get("https://api.covid19api.com/summary");
  13 + return CasesModel.fromJson(response.data);
  14 + } catch (e) {
  15 + print(e.toString());
  16 + return Future.error(e.toString());
  17 + }
  18 + }
  19 +}
  1 +import 'package:get_state/pages/home/domain/entity/cases_model.dart';
  2 +
  3 +abstract class IHomeRepository {
  4 + Future<CasesModel> getCases();
  5 +}
1 // To parse this JSON data, do 1 // To parse this JSON data, do
2 // 2 //
3 -// final apiModel = apiModelFromJson(jsonString); 3 +// final CasesModel = CasesModelFromJson(jsonString);
4 4
5 import 'dart:convert'; 5 import 'dart:convert';
6 6
7 -class ApiModel { 7 +class CasesModel {
8 final Global global; 8 final Global global;
9 final List<Country> countries; 9 final List<Country> countries;
10 final String date; 10 final String date;
11 11
12 - ApiModel({ 12 + CasesModel({
13 this.global, 13 this.global,
14 this.countries, 14 this.countries,
15 this.date, 15 this.date,
16 }); 16 });
17 17
18 - factory ApiModel.fromRawJson(String str) =>  
19 - ApiModel.fromJson(json.decode(str)); 18 + factory CasesModel.fromRawJson(String str) =>
  19 + CasesModel.fromJson(json.decode(str));
20 20
21 String toRawJson() => json.encode(toJson()); 21 String toRawJson() => json.encode(toJson());
22 22
23 - factory ApiModel.fromJson(Map<String, dynamic> json) => ApiModel( 23 + factory CasesModel.fromJson(Map<String, dynamic> json) => CasesModel(
24 global: json["Global"] == null ? null : Global.fromJson(json["Global"]), 24 global: json["Global"] == null ? null : Global.fromJson(json["Global"]),
25 countries: json["Countries"] == null 25 countries: json["Countries"] == null
26 ? null 26 ? null
  1 +import 'package:get/get.dart';
  2 +import 'package:get_state/pages/home/domain/adapters/repository_adapter.dart';
  3 +import 'package:get_state/pages/home/domain/entity/cases_model.dart';
  4 +
  5 +enum Status { loading, success, error }
  6 +
  7 +class HomeController extends GetxController {
  8 + HomeController({this.homeRepository});
  9 +
  10 + /// inject repo abstraction dependency
  11 + final IHomeRepository homeRepository;
  12 +
  13 + /// create a reactive status from request with initial value = loading
  14 + final status = Status.loading.obs;
  15 +
  16 + /// create a reactive CasesModel. CasesModel().obs has same result
  17 + final cases = Rx<CasesModel>();
  18 +
  19 + /// When the controller is initialized, make the http request
  20 + @override
  21 + void onInit() => fetchDataFromApi();
  22 +
  23 + /// fetch cases from Api
  24 + Future<void> fetchDataFromApi() async {
  25 + /// When the repository returns the value, change the status to success, and fill in "cases"
  26 + return homeRepository.getCases().then(
  27 + (data) {
  28 + cases(data);
  29 + status(Status.success);
  30 + },
  31 +
  32 + /// In case of error, print the error and change the status to Status.error
  33 + onError: (err) {
  34 + print("$err");
  35 + return status(Status.error);
  36 + },
  37 + );
  38 + }
  39 +}
1 import 'dart:ui'; 1 import 'dart:ui';
2 import 'package:flutter/material.dart'; 2 import 'package:flutter/material.dart';
3 -import 'package:get_state/home/controllers/home_controller.dart';  
4 -import 'package:get_state/home/data/home_model.dart';  
5 import 'package:get/get.dart'; 3 import 'package:get/get.dart';
  4 +import 'package:get_state/pages/home/domain/entity/cases_model.dart';
  5 +import '../controllers/home_controller.dart';
6 6
7 -class CountryPage extends GetWidget<HomeController> { 7 +class CountryView extends GetWidget<HomeController> {
8 @override 8 @override
9 Widget build(BuildContext context) { 9 Widget build(BuildContext context) {
10 return Container( 10 return Container(
@@ -28,9 +28,9 @@ class CountryPage extends GetWidget<HomeController> { @@ -28,9 +28,9 @@ class CountryPage extends GetWidget<HomeController> {
28 ), 28 ),
29 body: Center( 29 body: Center(
30 child: ListView.builder( 30 child: ListView.builder(
31 - itemCount: controller.data.value.countries.length, 31 + itemCount: controller.cases.value.countries.length,
32 itemBuilder: (context, index) { 32 itemBuilder: (context, index) {
33 - Country country = controller.data.value.countries[index]; 33 + Country country = controller.cases.value.countries[index];
34 return ListTile( 34 return ListTile(
35 onTap: () { 35 onTap: () {
36 Get.toNamed('/details', arguments: country); 36 Get.toNamed('/details', arguments: country);
1 import 'dart:ui'; 1 import 'dart:ui';
2 import 'package:flutter/material.dart'; 2 import 'package:flutter/material.dart';
3 import 'package:get/get.dart'; 3 import 'package:get/get.dart';
4 -import 'package:get_state/home/data/home_model.dart'; 4 +import 'package:get_state/pages/home/domain/entity/cases_model.dart';
5 5
6 -class DetailsPage extends StatelessWidget { 6 +class DetailsView extends StatelessWidget {
7 @override 7 @override
8 Widget build(BuildContext context) { 8 Widget build(BuildContext context) {
9 Country country = Get.arguments; 9 Country country = Get.arguments;
1 import 'dart:ui'; 1 import 'dart:ui';
2 import 'package:flutter/material.dart'; 2 import 'package:flutter/material.dart';
3 import 'package:get/get.dart'; 3 import 'package:get/get.dart';
4 -import 'package:get_state/home/controllers/home_controller.dart'; 4 +import 'package:get_state/pages/home/presentation/controllers/home_controller.dart';
5 5
6 -class HomePage extends GetWidget<HomeController> { 6 +class HomeView extends GetView<HomeController> {
7 @override 7 @override
8 Widget build(BuildContext context) { 8 Widget build(BuildContext context) {
9 return Container( 9 return Container(
@@ -23,9 +23,12 @@ class HomePage extends GetWidget<HomeController> { @@ -23,9 +23,12 @@ class HomePage extends GetWidget<HomeController> {
23 centerTitle: true, 23 centerTitle: true,
24 ), 24 ),
25 body: Center( 25 body: Center(
26 - child: Obx(() => (controller.data() == null)  
27 - ? CircularProgressIndicator()  
28 - : Column( 26 + child: Obx(
  27 + () {
  28 + Status status = controller.status.value;
  29 + if (status == Status.loading) return CircularProgressIndicator();
  30 + if (status == Status.error) return Text('Error on connection :(');
  31 + return Column(
29 mainAxisAlignment: MainAxisAlignment.center, 32 mainAxisAlignment: MainAxisAlignment.center,
30 children: [ 33 children: [
31 SizedBox( 34 SizedBox(
@@ -38,9 +41,8 @@ class HomePage extends GetWidget<HomeController> { @@ -38,9 +41,8 @@ class HomePage extends GetWidget<HomeController> {
38 ), 41 ),
39 ), 42 ),
40 Text( 43 Text(
41 - '${controller.data.value.global.totalConfirmed}',  
42 - style:  
43 - TextStyle(fontSize: 45, fontWeight: FontWeight.bold), 44 + '${controller.cases.value.global.totalConfirmed}',
  45 + style: TextStyle(fontSize: 45, fontWeight: FontWeight.bold),
44 ), 46 ),
45 SizedBox( 47 SizedBox(
46 height: 10, 48 height: 10,
@@ -52,9 +54,8 @@ class HomePage extends GetWidget<HomeController> { @@ -52,9 +54,8 @@ class HomePage extends GetWidget<HomeController> {
52 ), 54 ),
53 ), 55 ),
54 Text( 56 Text(
55 - '${controller.data.value.global.totalDeaths}',  
56 - style:  
57 - TextStyle(fontSize: 45, fontWeight: FontWeight.bold), 57 + '${controller.cases.value.global.totalDeaths}',
  58 + style: TextStyle(fontSize: 45, fontWeight: FontWeight.bold),
58 ), 59 ),
59 SizedBox( 60 SizedBox(
60 height: 10, 61 height: 10,
@@ -74,7 +75,9 @@ class HomePage extends GetWidget<HomeController> { @@ -74,7 +75,9 @@ class HomePage extends GetWidget<HomeController> {
74 ), 75 ),
75 ) 76 )
76 ], 77 ],
77 - )), 78 + );
  79 + },
  80 + ),
78 ), 81 ),
79 ), 82 ),
80 ); 83 );
  1 +import 'package:get/get.dart';
  2 +import 'package:get_state/pages/home/bindings/home_binding.dart';
  3 +import 'package:get_state/pages/home/presentation/views/country_view.dart';
  4 +import 'package:get_state/pages/home/presentation/views/details_view.dart';
  5 +import 'package:get_state/pages/home/presentation/views/home_view.dart';
  6 +
  7 +part 'app_routes.dart';
  8 +
  9 +class AppPages {
  10 + static const INITIAL = Routes.HOME;
  11 +
  12 + static final routes = [
  13 + GetPage(
  14 + name: Routes.HOME,
  15 + page: () => HomeView(),
  16 + binding: HomeBinding(),
  17 + ),
  18 + GetPage(
  19 + name: Routes.COUNTRY,
  20 + page: () => CountryView(),
  21 + ),
  22 + GetPage(
  23 + name: Routes.DETAILS,
  24 + page: () => DetailsView(),
  25 + ),
  26 + ];
  27 +}
  1 +part of 'app_pages.dart';
  2 +
  3 +abstract class Routes{
  4 +
  5 + static const HOME = '/home';
  6 + static const COUNTRY = '/country';
  7 + static const DETAILS = '/details';
  8 +}
  1 +class Logger {
  2 + // Sample of abstract logging function
  3 + static void write(String text, {bool isError = false}) {
  4 + print('** ' + text + ' [' + isError.toString() + ']');
  5 + }
  6 +}
  1 +flutter/ephemeral
  1 +cmake_minimum_required(VERSION 3.10)
  2 +project(runner LANGUAGES CXX)
  3 +
  4 +set(BINARY_NAME "example")
  5 +set(APPLICATION_ID "com.example.example")
  6 +
  7 +cmake_policy(SET CMP0063 NEW)
  8 +
  9 +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
  10 +
  11 +# Configure build options.
  12 +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
  13 + set(CMAKE_BUILD_TYPE "Debug" CACHE
  14 + STRING "Flutter build mode" FORCE)
  15 + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
  16 + "Debug" "Profile" "Release")
  17 +endif()
  18 +
  19 +# Compilation settings that should be applied to most targets.
  20 +function(APPLY_STANDARD_SETTINGS TARGET)
  21 + target_compile_features(${TARGET} PUBLIC cxx_std_14)
  22 + target_compile_options(${TARGET} PRIVATE -Wall -Werror)
  23 + target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
  24 + target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
  25 +endfunction()
  26 +
  27 +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
  28 +
  29 +# Flutter library and tool build rules.
  30 +add_subdirectory(${FLUTTER_MANAGED_DIR})
  31 +
  32 +# System-level dependencies.
  33 +find_package(PkgConfig REQUIRED)
  34 +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
  35 +
  36 +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
  37 +
  38 +# Application build
  39 +add_executable(${BINARY_NAME}
  40 + "main.cc"
  41 + "my_application.cc"
  42 + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
  43 +)
  44 +apply_standard_settings(${BINARY_NAME})
  45 +target_link_libraries(${BINARY_NAME} PRIVATE flutter)
  46 +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
  47 +add_dependencies(${BINARY_NAME} flutter_assemble)
  48 +
  49 +# Generated plugin build rules, which manage building the plugins and adding
  50 +# them to the application.
  51 +include(flutter/generated_plugins.cmake)
  52 +
  53 +
  54 +# === Installation ===
  55 +# By default, "installing" just makes a relocatable bundle in the build
  56 +# directory.
  57 +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
  58 +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
  59 + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
  60 +endif()
  61 +
  62 +# Start with a clean build bundle directory every time.
  63 +install(CODE "
  64 + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
  65 + " COMPONENT Runtime)
  66 +
  67 +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
  68 +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
  69 +
  70 +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
  71 + COMPONENT Runtime)
  72 +
  73 +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
  74 + COMPONENT Runtime)
  75 +
  76 +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
  77 + COMPONENT Runtime)
  78 +
  79 +if(PLUGIN_BUNDLED_LIBRARIES)
  80 + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}"
  81 + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
  82 + COMPONENT Runtime)
  83 +endif()
  84 +
  85 +# Fully re-copy the assets directory on each build to avoid having stale files
  86 +# from a previous install.
  87 +set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
  88 +install(CODE "
  89 + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
  90 + " COMPONENT Runtime)
  91 +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
  92 + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
  93 +
  94 +# Install the AOT library on non-Debug builds only.
  95 +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
  96 + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
  97 + COMPONENT Runtime)
  98 +endif()
  1 +cmake_minimum_required(VERSION 3.10)
  2 +
  3 +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
  4 +
  5 +# Configuration provided via flutter tool.
  6 +include(${EPHEMERAL_DIR}/generated_config.cmake)
  7 +
  8 +# TODO: Move the rest of this into files in ephemeral. See
  9 +# https://github.com/flutter/flutter/issues/57146.
  10 +
  11 +# Serves the same purpose as list(TRANSFORM ... PREPEND ...),
  12 +# which isn't available in 3.10.
  13 +function(list_prepend LIST_NAME PREFIX)
  14 + set(NEW_LIST "")
  15 + foreach(element ${${LIST_NAME}})
  16 + list(APPEND NEW_LIST "${PREFIX}${element}")
  17 + endforeach(element)
  18 + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
  19 +endfunction()
  20 +
  21 +# === Flutter Library ===
  22 +# System-level dependencies.
  23 +find_package(PkgConfig REQUIRED)
  24 +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
  25 +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
  26 +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
  27 +pkg_check_modules(BLKID REQUIRED IMPORTED_TARGET blkid)
  28 +
  29 +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")
  30 +
  31 +# Published to parent scope for install step.
  32 +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
  33 +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
  34 +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
  35 +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)
  36 +
  37 +list(APPEND FLUTTER_LIBRARY_HEADERS
  38 + "fl_basic_message_channel.h"
  39 + "fl_binary_codec.h"
  40 + "fl_binary_messenger.h"
  41 + "fl_dart_project.h"
  42 + "fl_engine.h"
  43 + "fl_json_message_codec.h"
  44 + "fl_json_method_codec.h"
  45 + "fl_message_codec.h"
  46 + "fl_method_call.h"
  47 + "fl_method_channel.h"
  48 + "fl_method_codec.h"
  49 + "fl_method_response.h"
  50 + "fl_plugin_registrar.h"
  51 + "fl_plugin_registry.h"
  52 + "fl_standard_message_codec.h"
  53 + "fl_standard_method_codec.h"
  54 + "fl_string_codec.h"
  55 + "fl_value.h"
  56 + "fl_view.h"
  57 + "flutter_linux.h"
  58 +)
  59 +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
  60 +add_library(flutter INTERFACE)
  61 +target_include_directories(flutter INTERFACE
  62 + "${EPHEMERAL_DIR}"
  63 +)
  64 +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
  65 +target_link_libraries(flutter INTERFACE
  66 + PkgConfig::GTK
  67 + PkgConfig::GLIB
  68 + PkgConfig::GIO
  69 + PkgConfig::BLKID
  70 +)
  71 +add_dependencies(flutter flutter_assemble)
  72 +
  73 +# === Flutter tool backend ===
  74 +# _phony_ is a non-existent file to force this command to run every time,
  75 +# since currently there's no way to get a full input/output list from the
  76 +# flutter tool.
  77 +add_custom_command(
  78 + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
  79 + ${CMAKE_CURRENT_BINARY_DIR}/_phony_
  80 + COMMAND ${CMAKE_COMMAND} -E env
  81 + ${FLUTTER_TOOL_ENVIRONMENT}
  82 + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
  83 + linux-x64 ${CMAKE_BUILD_TYPE}
  84 +)
  85 +add_custom_target(flutter_assemble DEPENDS
  86 + "${FLUTTER_LIBRARY}"
  87 + ${FLUTTER_LIBRARY_HEADERS}
  88 +)
  1 +//
  2 +// Generated file. Do not edit.
  3 +//
  4 +
  5 +#include "generated_plugin_registrant.h"
  6 +
  7 +
  8 +void fl_register_plugins(FlPluginRegistry* registry) {
  9 +}
  1 +//
  2 +// Generated file. Do not edit.
  3 +//
  4 +
  5 +#ifndef GENERATED_PLUGIN_REGISTRANT_
  6 +#define GENERATED_PLUGIN_REGISTRANT_
  7 +
  8 +#include <flutter_linux/flutter_linux.h>
  9 +
  10 +// Registers Flutter plugins.
  11 +void fl_register_plugins(FlPluginRegistry* registry);
  12 +
  13 +#endif // GENERATED_PLUGIN_REGISTRANT_
  1 +#
  2 +# Generated file, do not edit.
  3 +#
  4 +
  5 +list(APPEND FLUTTER_PLUGIN_LIST
  6 +)
  7 +
  8 +set(PLUGIN_BUNDLED_LIBRARIES)
  9 +
  10 +foreach(plugin ${FLUTTER_PLUGIN_LIST})
  11 + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
  12 + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
  13 + list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
  14 + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
  15 +endforeach(plugin)
  1 +#include "my_application.h"
  2 +
  3 +int main(int argc, char** argv) {
  4 + // Only X11 is currently supported.
  5 + // Wayland support is being developed: https://github.com/flutter/flutter/issues/57932.
  6 + gdk_set_allowed_backends("x11");
  7 +
  8 + g_autoptr(MyApplication) app = my_application_new();
  9 + return g_application_run(G_APPLICATION(app), argc, argv);
  10 +}
  1 +#include "my_application.h"
  2 +
  3 +#include <flutter_linux/flutter_linux.h>
  4 +
  5 +#include "flutter/generated_plugin_registrant.h"
  6 +
  7 +struct _MyApplication {
  8 + GtkApplication parent_instance;
  9 +};
  10 +
  11 +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
  12 +
  13 +// Implements GApplication::activate.
  14 +static void my_application_activate(GApplication* application) {
  15 + GtkWindow* window =
  16 + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
  17 + GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
  18 + gtk_widget_show(GTK_WIDGET(header_bar));
  19 + gtk_header_bar_set_title(header_bar, "example");
  20 + gtk_header_bar_set_show_close_button(header_bar, TRUE);
  21 + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
  22 + gtk_window_set_default_size(window, 1280, 720);
  23 + gtk_widget_show(GTK_WIDGET(window));
  24 +
  25 + g_autoptr(FlDartProject) project = fl_dart_project_new();
  26 +
  27 + FlView* view = fl_view_new(project);
  28 + gtk_widget_show(GTK_WIDGET(view));
  29 + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
  30 +
  31 + fl_register_plugins(FL_PLUGIN_REGISTRY(view));
  32 +
  33 + gtk_widget_grab_focus(GTK_WIDGET(view));
  34 +}
  35 +
  36 +static void my_application_class_init(MyApplicationClass* klass) {
  37 + G_APPLICATION_CLASS(klass)->activate = my_application_activate;
  38 +}
  39 +
  40 +static void my_application_init(MyApplication* self) {}
  41 +
  42 +MyApplication* my_application_new() {
  43 + return MY_APPLICATION(g_object_new(my_application_get_type(),
  44 + "application-id", APPLICATION_ID,
  45 + nullptr));
  46 +}
  1 +#ifndef FLUTTER_MY_APPLICATION_H_
  2 +#define FLUTTER_MY_APPLICATION_H_
  3 +
  4 +#include <gtk/gtk.h>
  5 +
  6 +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION,
  7 + GtkApplication)
  8 +
  9 +/**
  10 + * my_application_new:
  11 + *
  12 + * Creates a new Flutter-based application.
  13 + *
  14 + * Returns: a new #MyApplication.
  15 + */
  16 +MyApplication* my_application_new();
  17 +
  18 +#endif // FLUTTER_MY_APPLICATION_H_
1 # Generated by pub 1 # Generated by pub
2 # See https://dart.dev/tools/pub/glossary#lockfile 2 # See https://dart.dev/tools/pub/glossary#lockfile
3 packages: 3 packages:
  4 + _fe_analyzer_shared:
  5 + dependency: transitive
  6 + description:
  7 + name: _fe_analyzer_shared
  8 + url: "https://pub.dartlang.org"
  9 + source: hosted
  10 + version: "7.0.0"
  11 + analyzer:
  12 + dependency: transitive
  13 + description:
  14 + name: analyzer
  15 + url: "https://pub.dartlang.org"
  16 + source: hosted
  17 + version: "0.39.17"
  18 + args:
  19 + dependency: transitive
  20 + description:
  21 + name: args
  22 + url: "https://pub.dartlang.org"
  23 + source: hosted
  24 + version: "1.6.0"
4 async: 25 async:
5 dependency: transitive 26 dependency: transitive
6 description: 27 description:
@@ -15,6 +36,27 @@ packages: @@ -15,6 +36,27 @@ packages:
15 url: "https://pub.dartlang.org" 36 url: "https://pub.dartlang.org"
16 source: hosted 37 source: hosted
17 version: "2.1.0-nullsafety" 38 version: "2.1.0-nullsafety"
  39 + build:
  40 + dependency: transitive
  41 + description:
  42 + name: build
  43 + url: "https://pub.dartlang.org"
  44 + source: hosted
  45 + version: "1.3.0"
  46 + built_collection:
  47 + dependency: transitive
  48 + description:
  49 + name: built_collection
  50 + url: "https://pub.dartlang.org"
  51 + source: hosted
  52 + version: "4.3.2"
  53 + built_value:
  54 + dependency: transitive
  55 + description:
  56 + name: built_value
  57 + url: "https://pub.dartlang.org"
  58 + source: hosted
  59 + version: "7.1.0"
18 characters: 60 characters:
19 dependency: transitive 61 dependency: transitive
20 description: 62 description:
@@ -29,6 +71,13 @@ packages: @@ -29,6 +71,13 @@ packages:
29 url: "https://pub.dartlang.org" 71 url: "https://pub.dartlang.org"
30 source: hosted 72 source: hosted
31 version: "1.2.0-nullsafety" 73 version: "1.2.0-nullsafety"
  74 + cli_util:
  75 + dependency: transitive
  76 + description:
  77 + name: cli_util
  78 + url: "https://pub.dartlang.org"
  79 + source: hosted
  80 + version: "0.2.0"
32 clock: 81 clock:
33 dependency: transitive 82 dependency: transitive
34 description: 83 description:
@@ -36,6 +85,13 @@ packages: @@ -36,6 +85,13 @@ packages:
36 url: "https://pub.dartlang.org" 85 url: "https://pub.dartlang.org"
37 source: hosted 86 source: hosted
38 version: "1.1.0-nullsafety" 87 version: "1.1.0-nullsafety"
  88 + code_builder:
  89 + dependency: transitive
  90 + description:
  91 + name: code_builder
  92 + url: "https://pub.dartlang.org"
  93 + source: hosted
  94 + version: "3.4.1"
39 collection: 95 collection:
40 dependency: transitive 96 dependency: transitive
41 description: 97 description:
@@ -43,6 +99,34 @@ packages: @@ -43,6 +99,34 @@ packages:
43 url: "https://pub.dartlang.org" 99 url: "https://pub.dartlang.org"
44 source: hosted 100 source: hosted
45 version: "1.15.0-nullsafety.2" 101 version: "1.15.0-nullsafety.2"
  102 + convert:
  103 + dependency: transitive
  104 + description:
  105 + name: convert
  106 + url: "https://pub.dartlang.org"
  107 + source: hosted
  108 + version: "2.1.1"
  109 + crypto:
  110 + dependency: transitive
  111 + description:
  112 + name: crypto
  113 + url: "https://pub.dartlang.org"
  114 + source: hosted
  115 + version: "2.1.5"
  116 + csslib:
  117 + dependency: transitive
  118 + description:
  119 + name: csslib
  120 + url: "https://pub.dartlang.org"
  121 + source: hosted
  122 + version: "0.16.2"
  123 + dart_style:
  124 + dependency: transitive
  125 + description:
  126 + name: dart_style
  127 + url: "https://pub.dartlang.org"
  128 + source: hosted
  129 + version: "1.3.6"
46 dio: 130 dio:
47 dependency: "direct main" 131 dependency: "direct main"
48 description: 132 description:
@@ -57,6 +141,13 @@ packages: @@ -57,6 +141,13 @@ packages:
57 url: "https://pub.dartlang.org" 141 url: "https://pub.dartlang.org"
58 source: hosted 142 source: hosted
59 version: "1.1.0-nullsafety" 143 version: "1.1.0-nullsafety"
  144 + fixnum:
  145 + dependency: transitive
  146 + description:
  147 + name: fixnum
  148 + url: "https://pub.dartlang.org"
  149 + source: hosted
  150 + version: "0.10.11"
60 flutter: 151 flutter:
61 dependency: "direct main" 152 dependency: "direct main"
62 description: flutter 153 description: flutter
@@ -74,6 +165,20 @@ packages: @@ -74,6 +165,20 @@ packages:
74 relative: true 165 relative: true
75 source: path 166 source: path
76 version: "3.5.1" 167 version: "3.5.1"
  168 + glob:
  169 + dependency: transitive
  170 + description:
  171 + name: glob
  172 + url: "https://pub.dartlang.org"
  173 + source: hosted
  174 + version: "1.2.0"
  175 + html:
  176 + dependency: transitive
  177 + description:
  178 + name: html
  179 + url: "https://pub.dartlang.org"
  180 + source: hosted
  181 + version: "0.14.0+3"
77 http_parser: 182 http_parser:
78 dependency: transitive 183 dependency: transitive
79 description: 184 description:
@@ -81,6 +186,20 @@ packages: @@ -81,6 +186,20 @@ packages:
81 url: "https://pub.dartlang.org" 186 url: "https://pub.dartlang.org"
82 source: hosted 187 source: hosted
83 version: "3.1.4" 188 version: "3.1.4"
  189 + js:
  190 + dependency: transitive
  191 + description:
  192 + name: js
  193 + url: "https://pub.dartlang.org"
  194 + source: hosted
  195 + version: "0.6.2"
  196 + logging:
  197 + dependency: transitive
  198 + description:
  199 + name: logging
  200 + url: "https://pub.dartlang.org"
  201 + source: hosted
  202 + version: "0.11.4"
84 matcher: 203 matcher:
85 dependency: transitive 204 dependency: transitive
86 description: 205 description:
@@ -95,6 +214,34 @@ packages: @@ -95,6 +214,34 @@ packages:
95 url: "https://pub.dartlang.org" 214 url: "https://pub.dartlang.org"
96 source: hosted 215 source: hosted
97 version: "1.3.0-nullsafety.2" 216 version: "1.3.0-nullsafety.2"
  217 + mockito:
  218 + dependency: "direct main"
  219 + description:
  220 + name: mockito
  221 + url: "https://pub.dartlang.org"
  222 + source: hosted
  223 + version: "4.1.2"
  224 + node_interop:
  225 + dependency: transitive
  226 + description:
  227 + name: node_interop
  228 + url: "https://pub.dartlang.org"
  229 + source: hosted
  230 + version: "1.1.1"
  231 + node_io:
  232 + dependency: transitive
  233 + description:
  234 + name: node_io
  235 + url: "https://pub.dartlang.org"
  236 + source: hosted
  237 + version: "1.1.1"
  238 + package_config:
  239 + dependency: transitive
  240 + description:
  241 + name: package_config
  242 + url: "https://pub.dartlang.org"
  243 + source: hosted
  244 + version: "1.9.3"
98 path: 245 path:
99 dependency: transitive 246 dependency: transitive
100 description: 247 description:
@@ -102,11 +249,39 @@ packages: @@ -102,11 +249,39 @@ packages:
102 url: "https://pub.dartlang.org" 249 url: "https://pub.dartlang.org"
103 source: hosted 250 source: hosted
104 version: "1.8.0-nullsafety" 251 version: "1.8.0-nullsafety"
  252 + pedantic:
  253 + dependency: transitive
  254 + description:
  255 + name: pedantic
  256 + url: "https://pub.dartlang.org"
  257 + source: hosted
  258 + version: "1.9.2"
  259 + pub_semver:
  260 + dependency: transitive
  261 + description:
  262 + name: pub_semver
  263 + url: "https://pub.dartlang.org"
  264 + source: hosted
  265 + version: "1.4.4"
  266 + quiver:
  267 + dependency: transitive
  268 + description:
  269 + name: quiver
  270 + url: "https://pub.dartlang.org"
  271 + source: hosted
  272 + version: "2.1.3"
105 sky_engine: 273 sky_engine:
106 dependency: transitive 274 dependency: transitive
107 description: flutter 275 description: flutter
108 source: sdk 276 source: sdk
109 version: "0.0.99" 277 version: "0.0.99"
  278 + source_gen:
  279 + dependency: transitive
  280 + description:
  281 + name: source_gen
  282 + url: "https://pub.dartlang.org"
  283 + source: hosted
  284 + version: "0.9.6"
110 source_span: 285 source_span:
111 dependency: transitive 286 dependency: transitive
112 description: 287 description:
@@ -163,5 +338,19 @@ packages: @@ -163,5 +338,19 @@ packages:
163 url: "https://pub.dartlang.org" 338 url: "https://pub.dartlang.org"
164 source: hosted 339 source: hosted
165 version: "2.1.0-nullsafety.2" 340 version: "2.1.0-nullsafety.2"
  341 + watcher:
  342 + dependency: transitive
  343 + description:
  344 + name: watcher
  345 + url: "https://pub.dartlang.org"
  346 + source: hosted
  347 + version: "0.9.7+15"
  348 + yaml:
  349 + dependency: transitive
  350 + description:
  351 + name: yaml
  352 + url: "https://pub.dartlang.org"
  353 + source: hosted
  354 + version: "2.2.1"
166 sdks: 355 sdks:
167 dart: ">=2.10.0-0.0.dev <2.10.0" 356 dart: ">=2.10.0-0.0.dev <2.10.0"
@@ -29,6 +29,7 @@ dependencies: @@ -29,6 +29,7 @@ dependencies:
29 get: 29 get:
30 path: ../ 30 path: ../
31 dio: ^3.0.9 31 dio: ^3.0.9
  32 + mockito: 4.1.2
32 33
33 dev_dependencies: 34 dev_dependencies:
34 flutter_test: 35 flutter_test:
  1 +import 'dart:math';
  2 +import 'package:flutter_test/flutter_test.dart';
  3 +import 'package:get/get.dart';
  4 +import 'package:get_state/pages/home/domain/adapters/repository_adapter.dart';
  5 +import 'package:get_state/pages/home/domain/entity/cases_model.dart';
  6 +import 'package:get_state/pages/home/presentation/controllers/home_controller.dart';
  7 +import 'package:matcher/matcher.dart';
  8 +
  9 +class MockReposity implements IHomeRepository {
  10 + @override
  11 + Future<CasesModel> getCases() async {
  12 + await Future.delayed(Duration(milliseconds: 100));
  13 + return Random().nextBool()
  14 + ? CasesModel(
  15 + global: Global(totalDeaths: 100, totalConfirmed: 200),
  16 + )
  17 + : Future.error('error');
  18 + }
  19 +}
  20 +
  21 +void main() {
  22 + final binding = BindingsBuilder(() {
  23 + Get.lazyPut<IHomeRepository>(() => MockReposity());
  24 + Get.lazyPut<HomeController>(
  25 + () => HomeController(homeRepository: Get.find()));
  26 + });
  27 +
  28 + test('Test Binding', () {
  29 + expect(Get.isPrepared<HomeController>(), false);
  30 + expect(Get.isPrepared<IHomeRepository>(), false);
  31 +
  32 + /// test you Binding class with BindingsBuilder
  33 + binding.builder();
  34 +
  35 + expect(Get.isPrepared<HomeController>(), true);
  36 + expect(Get.isPrepared<IHomeRepository>(), true);
  37 +
  38 + Get.reset();
  39 + });
  40 + test('Test Controller', () async {
  41 + /// Controller can't be on memory
  42 + expect(() => Get.find<HomeController>(), throwsA(TypeMatcher<String>()));
  43 +
  44 + /// build Binding
  45 + binding.builder();
  46 +
  47 + /// recover your controller
  48 + HomeController controller = Get.find();
  49 +
  50 + /// check if onInit was called
  51 + expect(controller.initialized, true);
  52 +
  53 + /// check initial Status
  54 + expect(controller.status.value, Status.loading);
  55 +
  56 + /// await time request
  57 + await Future.delayed(Duration(milliseconds: 100));
  58 +
  59 + if (controller.status.value == Status.error) {
  60 + expect(controller.cases.value, null);
  61 + }
  62 +
  63 + if (controller.status.value == Status.success) {
  64 + expect(controller.cases.value.global.totalDeaths, 100);
  65 + expect(controller.cases.value.global.totalConfirmed, 200);
  66 + }
  67 + });
  68 +}
1 -// // This is a basic Flutter widget test.  
2 -// //  
3 -// // To perform an interaction with a widget in your test, use the WidgetTester  
4 -// // utility that Flutter provides. For example, you can send tap and scroll  
5 -// // gestures. You can also use WidgetTester to find child widgets in the widget  
6 -// // tree, read text, and verify that the values of widget properties are correct.  
7 -  
8 -// import 'package:flutter/material.dart';  
9 -// import 'package:flutter_test/flutter_test.dart';  
10 -  
11 -// import 'package:get_state/main.dart';  
12 -  
13 -// void main() {  
14 -// testWidgets('Counter increments smoke test', (WidgetTester tester) async {  
15 -// // Build our app and trigger a frame.  
16 -// await tester.pumpWidget(MyApp());  
17 -  
18 -// // Verify that our counter starts at 0.  
19 -// expect(find.text('0'), findsOneWidget);  
20 -// expect(find.text('1'), findsNothing);  
21 -  
22 -// // Tap the '+' icon and trigger a frame.  
23 -// await tester.tap(find.byIcon(Icons.add));  
24 -// await tester.pump();  
25 -  
26 -// // Verify that our counter has incremented.  
27 -// expect(find.text('0'), findsNothing);  
28 -// expect(find.text('1'), findsOneWidget);  
29 -// });  
30 -// }  
@@ -3,11 +3,12 @@ import 'package:get/src/core/get_interface.dart'; @@ -3,11 +3,12 @@ import 'package:get/src/core/get_interface.dart';
3 import 'get_instance.dart'; 3 import 'get_instance.dart';
4 4
5 extension Inst on GetInterface { 5 extension Inst on GetInterface {
6 - void lazyPut<S>(FcBuilderFunc builder, {String tag, bool fenix = false}) { 6 + void lazyPut<S>(InstanceBuilderCallback<S> builder,
  7 + {String tag, bool fenix = false}) {
7 return GetInstance().lazyPut<S>(builder, tag: tag, fenix: fenix); 8 return GetInstance().lazyPut<S>(builder, tag: tag, fenix: fenix);
8 } 9 }
9 10
10 - Future<S> putAsync<S>(FcBuilderFuncAsync<S> builder, 11 + Future<S> putAsync<S>(AsyncInstanceBuilderCallback<S> builder,
11 {String tag, bool permanent = false}) async => 12 {String tag, bool permanent = false}) async =>
12 GetInstance().putAsync<S>(builder, tag: tag, permanent: permanent); 13 GetInstance().putAsync<S>(builder, tag: tag, permanent: permanent);
13 14
@@ -22,7 +23,7 @@ extension Inst on GetInterface { @@ -22,7 +23,7 @@ extension Inst on GetInterface {
22 /// Repl b = find(); 23 /// Repl b = find();
23 /// print(a==b); (false)``` 24 /// print(a==b); (false)```
24 /// 25 ///
25 - void create<S>(FcBuilderFunc<S> builder, 26 + void create<S>(InstanceBuilderCallback<S> builder,
26 {String name, bool permanent = true}) => 27 {String name, bool permanent = true}) =>
27 GetInstance().create<S>(builder, name: name, permanent: permanent); 28 GetInstance().create<S>(builder, name: name, permanent: permanent);
28 29
@@ -42,7 +43,9 @@ extension Inst on GetInterface { @@ -42,7 +43,9 @@ extension Inst on GetInterface {
42 /// rules 43 /// rules
43 /// 44 ///
44 S put<S>(S dependency, 45 S put<S>(S dependency,
45 - {String tag, bool permanent = false, FcBuilderFunc<S> builder}) => 46 + {String tag,
  47 + bool permanent = false,
  48 + InstanceBuilderCallback<S> builder}) =>
46 GetInstance() 49 GetInstance()
47 .put<S>(dependency, tag: tag, permanent: permanent, builder: builder); 50 .put<S>(dependency, tag: tag, permanent: permanent, builder: builder);
48 51
@@ -55,4 +58,6 @@ extension Inst on GetInterface { @@ -55,4 +58,6 @@ extension Inst on GetInterface {
55 GetInstance().delete<S>(tag: tag, key: key); 58 GetInstance().delete<S>(tag: tag, key: key);
56 59
57 bool isRegistered<S>({String tag}) => GetInstance().isRegistered<S>(tag: tag); 60 bool isRegistered<S>({String tag}) => GetInstance().isRegistered<S>(tag: tag);
  61 +
  62 + bool isPrepared<S>({String tag}) => GetInstance().isPrepared<S>(tag: tag);
58 } 63 }
@@ -27,12 +27,13 @@ class GetInstance { @@ -27,12 +27,13 @@ class GetInstance {
27 27
28 static GetQueue _queue = GetQueue(); 28 static GetQueue _queue = GetQueue();
29 29
30 - void lazyPut<S>(FcBuilderFunc builder, {String tag, bool fenix = false}) { 30 + void lazyPut<S>(InstanceBuilderCallback<S> builder,
  31 + {String tag, bool fenix = false}) {
31 String key = _getKey(S, tag); 32 String key = _getKey(S, tag);
32 _factory.putIfAbsent(key, () => _Lazy(builder, fenix)); 33 _factory.putIfAbsent(key, () => _Lazy(builder, fenix));
33 } 34 }
34 35
35 - Future<S> putAsync<S>(FcBuilderFuncAsync<S> builder, 36 + Future<S> putAsync<S>(AsyncInstanceBuilderCallback<S> builder,
36 {String tag, bool permanent = false}) async { 37 {String tag, bool permanent = false}) async {
37 return put<S>(await builder(), tag: tag, permanent: permanent); 38 return put<S>(await builder(), tag: tag, permanent: permanent);
38 } 39 }
@@ -49,7 +50,7 @@ class GetInstance { @@ -49,7 +50,7 @@ class GetInstance {
49 S dependency, { 50 S dependency, {
50 String tag, 51 String tag,
51 bool permanent = false, 52 bool permanent = false,
52 - FcBuilderFunc<S> builder, 53 + InstanceBuilderCallback<S> builder,
53 }) { 54 }) {
54 _insert( 55 _insert(
55 isSingleton: true, 56 isSingleton: true,
@@ -70,7 +71,7 @@ class GetInstance { @@ -70,7 +71,7 @@ class GetInstance {
70 /// Repl b = find(); 71 /// Repl b = find();
71 /// print(a==b); (false)``` 72 /// print(a==b); (false)```
72 void create<S>( 73 void create<S>(
73 - FcBuilderFunc<S> builder, { 74 + InstanceBuilderCallback<S> builder, {
74 String name, 75 String name,
75 bool permanent = true, 76 bool permanent = true,
76 }) { 77 }) {
@@ -83,7 +84,7 @@ class GetInstance { @@ -83,7 +84,7 @@ class GetInstance {
83 bool isSingleton, 84 bool isSingleton,
84 String name, 85 String name,
85 bool permanent = false, 86 bool permanent = false,
86 - FcBuilderFunc<S> builder, 87 + InstanceBuilderCallback<S> builder,
87 }) { 88 }) {
88 assert(builder != null); 89 assert(builder != null);
89 final key = _getKey(S, name); 90 final key = _getKey(S, name);
@@ -180,7 +181,7 @@ class GetInstance { @@ -180,7 +181,7 @@ class GetInstance {
180 S find<S>({String tag}) { 181 S find<S>({String tag}) {
181 String key = _getKey(S, tag); 182 String key = _getKey(S, tag);
182 if (isRegistered<S>(tag: tag)) { 183 if (isRegistered<S>(tag: tag)) {
183 - _FcBuilder builder = _singl[key] as _FcBuilder; 184 + _FcBuilder builder = _singl[key];
184 if (builder == null) { 185 if (builder == null) {
185 if (tag == null) { 186 if (tag == null) {
186 throw 'Class "$S" is not register'; 187 throw 'Class "$S" is not register';
@@ -245,7 +246,7 @@ class GetInstance { @@ -245,7 +246,7 @@ class GetInstance {
245 return false; 246 return false;
246 } 247 }
247 248
248 - _FcBuilder builder = _singl[newKey] as _FcBuilder; 249 + _FcBuilder builder = _singl[newKey];
249 if (builder.permanent && !force) { 250 if (builder.permanent && !force) {
250 GetConfig.log( 251 GetConfig.log(
251 '"$newKey" has been marked as permanent, SmartManagement is not authorized to delete it.', 252 '"$newKey" has been marked as permanent, SmartManagement is not authorized to delete it.',
@@ -280,9 +281,9 @@ class GetInstance { @@ -280,9 +281,9 @@ class GetInstance {
280 bool isPrepared<S>({String tag}) => _factory.containsKey(_getKey(S, tag)); 281 bool isPrepared<S>({String tag}) => _factory.containsKey(_getKey(S, tag));
281 } 282 }
282 283
283 -typedef FcBuilderFunc<S> = S Function(); 284 +typedef InstanceBuilderCallback<S> = S Function();
284 285
285 -typedef FcBuilderFuncAsync<S> = Future<S> Function(); 286 +typedef AsyncInstanceBuilderCallback<S> = Future<S> Function();
286 287
287 /// Internal class to register instances with Get.[put]<[S]>(). 288 /// Internal class to register instances with Get.[put]<[S]>().
288 class _FcBuilder<S> { 289 class _FcBuilder<S> {
@@ -295,7 +296,7 @@ class _FcBuilder<S> { @@ -295,7 +296,7 @@ class _FcBuilder<S> {
295 296
296 /// Generates (and regenerates) the instance when [isSingleton]=false. 297 /// Generates (and regenerates) the instance when [isSingleton]=false.
297 /// Usually used by factory methods 298 /// Usually used by factory methods
298 - FcBuilderFunc<S> builderFunc; 299 + InstanceBuilderCallback<S> builderFunc;
299 300
300 /// Flag to persist the instance in memory, 301 /// Flag to persist the instance in memory,
301 /// without considering [GetConfig.smartManagement] 302 /// without considering [GetConfig.smartManagement]
@@ -315,6 +316,6 @@ class _FcBuilder<S> { @@ -315,6 +316,6 @@ class _FcBuilder<S> {
315 /// keeps a reference to the callback to be called. 316 /// keeps a reference to the callback to be called.
316 class _Lazy { 317 class _Lazy {
317 bool fenix; 318 bool fenix;
318 - FcBuilderFunc builder; 319 + InstanceBuilderCallback builder;
319 _Lazy(this.builder, this.fenix); 320 _Lazy(this.builder, this.fenix);
320 } 321 }
@@ -730,7 +730,7 @@ extension GetNavigation on GetInterface { @@ -730,7 +730,7 @@ extension GetNavigation on GetInterface {
730 Text( 730 Text(
731 title, 731 title,
732 style: TextStyle( 732 style: TextStyle(
733 - color: colorText ?? theme.iconTheme.color, 733 + color: colorText ?? Colors.black,
734 fontWeight: FontWeight.w800, 734 fontWeight: FontWeight.w800,
735 fontSize: 16), 735 fontSize: 16),
736 ), 736 ),
@@ -738,7 +738,7 @@ extension GetNavigation on GetInterface { @@ -738,7 +738,7 @@ extension GetNavigation on GetInterface {
738 Text( 738 Text(
739 message, 739 message,
740 style: TextStyle( 740 style: TextStyle(
741 - color: colorText ?? theme.iconTheme.color, 741 + color: colorText ?? Colors.black,
742 fontWeight: FontWeight.w300, 742 fontWeight: FontWeight.w300,
743 fontSize: 14), 743 fontSize: 14),
744 ), 744 ),
@@ -19,7 +19,7 @@ abstract class Bindings { @@ -19,7 +19,7 @@ abstract class Bindings {
19 /// ```` 19 /// ````
20 class BindingsBuilder extends Bindings { 20 class BindingsBuilder extends Bindings {
21 /// Register your dependencies in the [builder] callback. 21 /// Register your dependencies in the [builder] callback.
22 - final Function() builder; 22 + final void Function() builder;
23 23
24 BindingsBuilder(this.builder); 24 BindingsBuilder(this.builder);
25 25
@@ -42,9 +42,13 @@ abstract class DisposableInterface { @@ -42,9 +42,13 @@ abstract class DisposableInterface {
42 /// It uses an internal "callable" type, to avoid any @overrides in subclases. 42 /// It uses an internal "callable" type, to avoid any @overrides in subclases.
43 /// This method should be internal and is required to define the lifetime cycle 43 /// This method should be internal and is required to define the lifetime cycle
44 /// of the subclass. 44 /// of the subclass.
45 - ///  
46 final onStart = _InternalFinalCallback<void>(); 45 final onStart = _InternalFinalCallback<void>();
47 46
  47 + bool _initialized = false;
  48 +
  49 + /// Checks whether the controller has already been initialized.
  50 + bool get initialized => _initialized;
  51 +
48 DisposableInterface() { 52 DisposableInterface() {
49 onStart.callback = _onStart; 53 onStart.callback = _onStart;
50 } 54 }
@@ -52,6 +56,7 @@ abstract class DisposableInterface { @@ -52,6 +56,7 @@ abstract class DisposableInterface {
52 // Internal callback that starts the cycle of this controller. 56 // Internal callback that starts the cycle of this controller.
53 void _onStart() { 57 void _onStart() {
54 onInit(); 58 onInit();
  59 + _initialized = true;
55 SchedulerBinding.instance?.addPostFrameCallback((_) => onReady()); 60 SchedulerBinding.instance?.addPostFrameCallback((_) => onReady());
56 } 61 }
57 62